<commit_before>use std::cell::UnsafeCell;
use std::mem;
use std::ptr;

/// `BytesRef` refers to a slice in tantivy's custom `Heap`.
#[derive(Copy, Clone)]
pub struct BytesRef {
    pub start: u32,
    pub stop: u32,
}

/// Object that can be allocated in tantivy's custom `Heap`.
pub trait HeapAllocable {
    fn with_addr(addr: u32) -> Self;
}

/// Tantivy's custom `Heap`.
pub struct Heap {
    inner: UnsafeCell<InnerHeap>,
}

impl Heap {
    /// Creates a new heap with a given capacity
    pub fn with_capacity(num_bytes: usize) -> Heap {
        Heap {
            inner: UnsafeCell::new(
                InnerHeap::with_capacity(num_bytes)
            ),
        }
    }

    fn inner(&self,) -> &mut InnerHeap {
        unsafe { &mut *self.inner.get() }
    }

    /// Clears the heap. All the underlying data is lost.
    ///
    /// This heap does not support deallocation.
    /// This method is the only way to free memory.
    pub fn clear(&self) {
        self.inner().clear();
    }

    /// Return the heap capacity.
    pub fn capacity(&self,) -> u32 {
        self.inner().capacity()
    }

    /// Return amount of free space, in bytes.
    pub fn num_free_bytes(&self,) -> u32 {
        self.inner().num_free_bytes()
    }

    /// Allocate a given amount of space and returns an address
    /// in the Heap.
    pub fn allocate_space(&self, num_bytes: usize) -> u32 {
        self.inner().allocate_space(num_bytes)
    }

    /// Allocate an object in the heap
    pub fn allocate_object<V: HeapAllocable>(&self,) -> (u32, &mut V) {
        let addr = self.inner().allocate_space(mem::size_of::<V>());
        let v: V = V::with_addr(addr);
        self.inner().set(addr, &v);
        (addr, self.inner().get_mut_ref(addr))
    }

    /// Stores a `&[u8]` in the heap and returns the destination BytesRef.
    pub fn allocate_and_set(&self, data: &[u8]) -> BytesRef {
        self.inner().allocate_and_set(data)
    }

    /// Fetches the `&[u8]` stored on the slice defined by the `BytesRef`
    /// given as argumetn
    pub fn get_slice(&self, bytes_ref: BytesRef) -> &[u8] {
        self.inner().get_slice(bytes_ref.start, bytes_ref.stop)
    }

    /// Stores an item's data in the heap, at the given `address`.
    pub fn set<Item>(&self, addr: u32, val: &Item) {
        self.inner().set(addr, val);
    }

    /// Returns a reference to an `Item` at a given `addr`.
    #[cfg(test)]
    pub fn get_ref<Item>(&self, addr: u32) -> &Item {
        self.inner().get_mut_ref(addr)
    }

    /// Returns a mutable reference to an `Item` at a given `addr`.
    pub fn get_mut_ref<Item>(&self, addr: u32) -> &mut Item {
        self.inner().get_mut_ref(addr)
    }
}

struct InnerHeap {
    buffer: Vec<u8>,
    buffer_len: u32,
    used: u32,
    next_heap: Option<Box<InnerHeap>>,
}

impl InnerHeap {

    pub fn with_capacity(num_bytes: usize) -> InnerHeap {
        let buffer: Vec<u8> = vec![0u8; num_bytes];
        InnerHeap {
            buffer: buffer,
            buffer_len: num_bytes as u32,
            next_heap: None,
            used: 0u32,
        }
    }

    pub fn clear(&mut self) {
        self.used = 0u32;
        self.next_heap = None;
    }

    pub fn capacity(&self,) -> u32 {
        self.buffer.len() as u32
    }

    // Returns the number of free bytes. If the buffer
    // has reached it's capacity and overflowed to another buffer, return 0.
    pub fn num_free_bytes(&self,) -> u32 {
        if self.next_heap.is_some() {
            0u32
        }
        else {
            self.buffer_len - self.used
        }
    }

    pub fn allocate_space(&mut self, num_bytes: usize) -> u32 {
        let addr = self.used;
        self.used += num_bytes as u32;
        if self.used <= self.buffer_len {
            addr
        }
        else {
            if self.next_heap.is_none() {
                warn!("Exceeded heap size. The margin was apparently unsufficient. The segment will be committed right after indexing this very last document.");
                self.next_heap = Some(Box::new(InnerHeap::with_capacity(self.buffer_len as usize)));
            }
            self.next_heap.as_mut().unwrap().allocate_space(num_bytes) + self.buffer_len
        }

    }

    fn get_slice(&self, start: u32, stop: u32) -> &[u8] {
        if start >= self.buffer_len {
            self.next_heap.as_ref().unwrap().get_slice(start - self.buffer_len, stop - self.buffer_len)
        }
        else {
            &self.buffer[start as usize..stop as usize]
        }
    }

    fn get_mut_slice(&mut self, start: u32, stop: u32) -> &mut [u8] {
        if start >= self.buffer_len {
            self.next_heap.as_mut().unwrap().get_mut_slice(start - self.buffer_len, stop - self.buffer_len)
        }
        else {
            &mut self.buffer[start as usize..stop as usize]
        }
    }

    fn allocate_and_set(&mut self, data: &[u8]) -> BytesRef {
        let start = self.allocate_space(data.len());
        let stop = start + data.len() as u32;
        self.get_mut_slice(start, stop).clone_from_slice(data);
        BytesRef {
            start: start as u32,
            stop: stop as u32,
        }
    }

    fn get_mut(&mut self, addr: u32) -> *mut u8 {
        if addr >= self.buffer_len {
            self.next_heap.as_mut().unwrap().get_mut(addr - self.buffer_len)
        }
        else {
            let addr_isize = addr as isize;
            unsafe { self.buffer.as_mut_ptr().offset(addr_isize) }
        }
    }

    fn get_mut_ref<Item>(&mut self, addr: u32) -> &mut Item {
        if addr >= self.buffer_len {
            self.next_heap.as_mut().unwrap().get_mut_ref(addr - self.buffer_len)
        }
        else {
            let v_ptr_u8 = self.get_mut(addr) as *mut u8;
            let v_ptr = v_ptr_u8 as *mut Item;
            unsafe { &mut *v_ptr }
        }
    }

    fn set<Item>(&mut self, addr: u32, val: &Item) {
        if addr >= self.buffer_len {
            self.next_heap.as_mut().unwrap().set(addr - self.buffer_len, val);
        }
        else {
            let v_ptr: *const Item = val as *const Item;
            let v_ptr_u8: *const u8 = v_ptr as *const u8;
            debug_assert!(addr + mem::size_of::<Item>() as u32 <= self.used);
            unsafe {
                let dest_ptr: *mut u8 = self.get_mut(addr);
                ptr::copy(v_ptr_u8, dest_ptr, mem::size_of::<Item>());
            }
        }
    }
}<commit_msg>Removed the clunky linked list logic of the heap.<commit_after>use std::cell::UnsafeCell;
use std::mem;
use std::ptr;

/// `BytesRef` refers to a slice in tantivy's custom `Heap`.
#[derive(Copy, Clone)]
pub struct BytesRef {
    pub start: u32,
    pub stop: u32,
}

/// Object that can be allocated in tantivy's custom `Heap`.
pub trait HeapAllocable {
    fn with_addr(addr: u32) -> Self;
}

/// Tantivy's custom `Heap`.
pub struct Heap {
    inner: UnsafeCell<InnerHeap>,
}

impl Heap {
    /// Creates a new heap with a given capacity
    pub fn with_capacity(num_bytes: usize) -> Heap {
        Heap {
            inner: UnsafeCell::new(
                InnerHeap::with_capacity(num_bytes)
            ),
        }
    }

    fn inner(&self,) -> &mut InnerHeap {
        unsafe { &mut *self.inner.get() }
    }

    /// Clears the heap. All the underlying data is lost.
    ///
    /// This heap does not support deallocation.
    /// This method is the only way to free memory.
    pub fn clear(&self) {
        self.inner().clear();
    }

    /// Return the heap capacity.
    pub fn capacity(&self,) -> u32 {
        self.inner().capacity()
    }

    /// Return amount of free space, in bytes.
    pub fn num_free_bytes(&self,) -> u32 {
        self.inner().num_free_bytes()
    }

    /// Allocate a given amount of space and returns an address
    /// in the Heap.
    pub fn allocate_space(&self, num_bytes: usize) -> u32 {
        self.inner().allocate_space(num_bytes)
    }

    /// Allocate an object in the heap
    pub fn allocate_object<V: HeapAllocable>(&self,) -> (u32, &mut V) {
        let addr = self.inner().allocate_space(mem::size_of::<V>());
        let v: V = V::with_addr(addr);
        self.inner().set(addr, &v);
        (addr, self.inner().get_mut_ref(addr))
    }

    /// Stores a `&[u8]` in the heap and returns the destination BytesRef.
    pub fn allocate_and_set(&self, data: &[u8]) -> BytesRef {
        self.inner().allocate_and_set(data)
    }

    /// Fetches the `&[u8]` stored on the slice defined by the `BytesRef`
    /// given as argumetn
    pub fn get_slice(&self, bytes_ref: BytesRef) -> &[u8] {
        self.inner().get_slice(bytes_ref.start, bytes_ref.stop)
    }

    /// Stores an item's data in the heap, at the given `address`.
    pub fn set<Item>(&self, addr: u32, val: &Item) {
        self.inner().set(addr, val);
    }

    /// Returns a reference to an `Item` at a given `addr`.
    #[cfg(test)]
    pub fn get_ref<Item>(&self, addr: u32) -> &Item {
        self.inner().get_mut_ref(addr)
    }

    /// Returns a mutable reference to an `Item` at a given `addr`.
    pub fn get_mut_ref<Item>(&self, addr: u32) -> &mut Item {
        self.inner().get_mut_ref(addr)
    }
}

struct InnerHeap {
    buffer: Vec<u8>,
    used: u32,
    has_been_resized: bool,
}

impl InnerHeap {

    pub fn with_capacity(num_bytes: usize) -> InnerHeap {
        let buffer: Vec<u8> = vec![0u8; num_bytes];
        InnerHeap {
            buffer: buffer,
            used: 0u32,
            has_been_resized: false,
        }
    }

    pub fn clear(&mut self) {
        self.used = 0u32;
    }

    pub fn capacity(&self,) -> u32 {
        self.buffer.len() as u32
    }

    // Returns the number of free bytes. If the buffer
    // has reached it's capacity and overflowed to another buffer, return 0.
    pub fn num_free_bytes(&self,) -> u32 {
        if self.has_been_resized {
            0u32
        }
        else {
            (self.buffer.len() as u32) - self.used
        }
    }

    pub fn allocate_space(&mut self, num_bytes: usize) -> u32 {
        let addr = self.used;
        self.used += num_bytes as u32;
        let buffer_len = self.buffer.len();
        if self.used > buffer_len as u32 {
            self.buffer.resize(buffer_len * 2, 0u8);
            self.has_been_resized = true
        }
        addr
    }

    fn get_slice(&self, start: u32, stop: u32) -> &[u8] {
        &self.buffer[start as usize..stop as usize]
    }

    fn get_mut_slice(&mut self, start: u32, stop: u32) -> &mut [u8] {
        &mut self.buffer[start as usize..stop as usize]
    }

    fn allocate_and_set(&mut self, data: &[u8]) -> BytesRef {
        let start = self.allocate_space(data.len());
        let stop = start + data.len() as u32;
        self.get_mut_slice(start, stop).clone_from_slice(data);
        BytesRef {
            start: start as u32,
            stop: stop as u32,
        }
    }

    fn get_mut(&mut self, addr: u32) -> *mut u8 {
        let addr_isize = addr as isize;
        unsafe { self.buffer.as_mut_ptr().offset(addr_isize) }
    }

    fn get_mut_ref<Item>(&mut self, addr: u32) -> &mut Item {
        let v_ptr_u8 = self.get_mut(addr) as *mut u8;
        let v_ptr = v_ptr_u8 as *mut Item;
        unsafe { &mut *v_ptr }
    }

    fn set<Item>(&mut self, addr: u32, val: &Item) {
        let v_ptr: *const Item = val as *const Item;
        let v_ptr_u8: *const u8 = v_ptr as *const u8;
        debug_assert!(addr + mem::size_of::<Item>() as u32 <= self.used);
        unsafe {
            let dest_ptr: *mut u8 = self.get_mut(addr);
            ptr::copy(v_ptr_u8, dest_ptr, mem::size_of::<Item>());
        }
    }
}<|endoftext|>


<commit_before>use serde::de::{Deserialize, Deserializer, Error};

use types::*;

/// This object represents a Telegram user or bot.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize)]
pub struct User {
    /// Unique identifier for this user or bot.
    pub id: UserId,
    /// User‘s or bot’s first name.
    pub first_name: String,
    /// User‘s or bot’s last name.
    pub last_name: Option<String>,
    /// User‘s or bot’s username.
    pub username: Option<String>,
    /// True, if this user is a bot.
    pub is_bot: bool,
}

/// This object represents a group.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize)]
pub struct Group {
    /// Unique identifier for this chat.
    pub id: GroupId,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// True if a group has ‘All Members Are Admins’ enabled.
    pub all_members_are_administrators: bool,
}

/// This object represents a supergroup.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize)]
pub struct Supergroup {
    /// Unique identifier for this chat.
    pub id: SupergroupId,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// Username for supergroup.
    pub username: Option<String>,
}

/// This object represents a channel.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize)]
pub struct Channel {
    /// Unique identifier for this chat.
    pub id: ChannelId,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// Username for channel.
    pub username: Option<String>,
}

/// This object represents a private, group or supergroup.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub enum MessageChat {
    Private(User),
    Group(Group),
    Supergroup(Supergroup),
    #[doc(hidden)]
    Unknown(RawChat),
}

impl MessageChat {
    pub fn id(&self) -> ChatId {
        match *self {
            MessageChat::Private(ref x) => x.id.into(),
            MessageChat::Group(ref x) => x.id.into(),
            MessageChat::Supergroup(ref x) => x.id.into(),
            MessageChat::Unknown(ref x) => x.id.into(),
        }
    }
}

/// This object represents a chat.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub enum Chat {
    Private(User),
    Group(Group),
    Supergroup(Supergroup),
    Channel(Channel),
    #[doc(hidden)]
    Unknown(RawChat),
}

impl Chat {
    pub fn id(&self) -> ChatId {
        match *self {
            Chat::Private(ref x) => x.id.into(),
            Chat::Group(ref x) => x.id.into(),
            Chat::Supergroup(ref x) => x.id.into(),
            Chat::Channel(ref x) => x.id.into(),
            Chat::Unknown(ref x) => x.id.into(),
        }
    }
}

impl<'de> Deserialize<'de> for Chat {
    fn deserialize<D>(deserializer: D) -> Result<Chat, D::Error>
        where D: Deserializer<'de>
    {
        let raw: RawChat = Deserialize::deserialize(deserializer)?;

        macro_rules! required_field {
            ($name:ident) => {{
                match raw.$name {
                    Some(val) => val,
                    None => return Err(D::Error::missing_field(stringify!($name)))
                }
            }}
        }

        Ok(match raw.type_.as_ref() {
            "private" => {
                Chat::Private(User {
                    id: raw.id.into(),
                    username: raw.username,
                    first_name: required_field!(first_name),
                    last_name: raw.last_name,
                })
            }
            "group" => {
                Chat::Group(Group {
                    id: raw.id.into(),
                    title: required_field!(title),
                    all_members_are_administrators: required_field!(all_members_are_administrators),
                })
            }
            "supergroup" => {
                Chat::Supergroup(Supergroup {
                    id: raw.id.into(),
                    title: required_field!(title),
                    username: raw.username,
                })
            }
            "channel" => {
                Chat::Channel(Channel {
                    id: raw.id.into(),
                    title: required_field!(title),
                    username: raw.username,
                })
            }
            _ => Chat::Unknown(raw),
        })
    }
}

/// This object represents a chat, directly mapped.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize)]
pub struct RawChat {
    /// Unique identifier for this chat.
    pub id: Integer,
    /// Type of chat, can be either “private”, “group”, “supergroup” or “channel”
    #[serde(rename="type")]
    pub type_: String,
    /// Title, for supergroups, channels and group chats
    pub title: Option<String>,
    /// Username, for private chats, supergroups and channels if available
    pub username: Option<String>,
    /// First name of the other party in a private chat
    pub first_name: Option<String>,
    /// Last name of the other party in a private chat
    pub last_name: Option<String>,
    /// True if a group has ‘All Members Are Admins’ enabled.
    pub all_members_are_administrators: Option<bool>,
}
<commit_msg>Added is_bot as false value if is in Chat structure<commit_after>use serde::de::{Deserialize, Deserializer, Error};

use types::*;

/// This object represents a Telegram user or bot.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize)]
pub struct User {
    /// Unique identifier for this user or bot.
    pub id: UserId,
    /// User‘s or bot’s first name.
    pub first_name: String,
    /// User‘s or bot’s last name.
    pub last_name: Option<String>,
    /// User‘s or bot’s username.
    pub username: Option<String>,
    /// True, if this user is a bot.
    pub is_bot: bool,
}

/// This object represents a group.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize)]
pub struct Group {
    /// Unique identifier for this chat.
    pub id: GroupId,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// True if a group has ‘All Members Are Admins’ enabled.
    pub all_members_are_administrators: bool,
}

/// This object represents a supergroup.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize)]
pub struct Supergroup {
    /// Unique identifier for this chat.
    pub id: SupergroupId,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// Username for supergroup.
    pub username: Option<String>,
}

/// This object represents a channel.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize)]
pub struct Channel {
    /// Unique identifier for this chat.
    pub id: ChannelId,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// Username for channel.
    pub username: Option<String>,
}

/// This object represents a private, group or supergroup.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub enum MessageChat {
    Private(User),
    Group(Group),
    Supergroup(Supergroup),
    #[doc(hidden)]
    Unknown(RawChat),
}

impl MessageChat {
    pub fn id(&self) -> ChatId {
        match *self {
            MessageChat::Private(ref x) => x.id.into(),
            MessageChat::Group(ref x) => x.id.into(),
            MessageChat::Supergroup(ref x) => x.id.into(),
            MessageChat::Unknown(ref x) => x.id.into(),
        }
    }
}

/// This object represents a chat.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub enum Chat {
    Private(User),
    Group(Group),
    Supergroup(Supergroup),
    Channel(Channel),
    #[doc(hidden)]
    Unknown(RawChat),
}

impl Chat {
    pub fn id(&self) -> ChatId {
        match *self {
            Chat::Private(ref x) => x.id.into(),
            Chat::Group(ref x) => x.id.into(),
            Chat::Supergroup(ref x) => x.id.into(),
            Chat::Channel(ref x) => x.id.into(),
            Chat::Unknown(ref x) => x.id.into(),
        }
    }
}

impl<'de> Deserialize<'de> for Chat {
    fn deserialize<D>(deserializer: D) -> Result<Chat, D::Error>
        where D: Deserializer<'de>
    {
        let raw: RawChat = Deserialize::deserialize(deserializer)?;

        macro_rules! required_field {
            ($name:ident) => {{
                match raw.$name {
                    Some(val) => val,
                    None => return Err(D::Error::missing_field(stringify!($name)))
                }
            }}
        }

        Ok(match raw.type_.as_ref() {
            "private" => {
                Chat::Private(User {
                    id: raw.id.into(),
                    username: raw.username,
                    first_name: required_field!(first_name),
                    last_name: raw.last_name,
                    is_bot: false,
                })
            }
            "group" => {
                Chat::Group(Group {
                    id: raw.id.into(),
                    title: required_field!(title),
                    all_members_are_administrators: required_field!(all_members_are_administrators),
                })
            }
            "supergroup" => {
                Chat::Supergroup(Supergroup {
                    id: raw.id.into(),
                    title: required_field!(title),
                    username: raw.username,
                })
            }
            "channel" => {
                Chat::Channel(Channel {
                    id: raw.id.into(),
                    title: required_field!(title),
                    username: raw.username,
                })
            }
            _ => Chat::Unknown(raw),
        })
    }
}

/// This object represents a chat, directly mapped.
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize)]
pub struct RawChat {
    /// Unique identifier for this chat.
    pub id: Integer,
    /// Type of chat, can be either “private”, “group”, “supergroup” or “channel”
    #[serde(rename="type")]
    pub type_: String,
    /// Title, for supergroups, channels and group chats
    pub title: Option<String>,
    /// Username, for private chats, supergroups and channels if available
    pub username: Option<String>,
    /// First name of the other party in a private chat
    pub first_name: Option<String>,
    /// Last name of the other party in a private chat
    pub last_name: Option<String>,
    /// True if a group has ‘All Members Are Admins’ enabled.
    pub all_members_are_administrators: Option<bool>,
}
<|endoftext|>


<commit_before>//! Handle `cargo add` arguments

#![allow(clippy::bool_assert_comparison)]

use cargo_edit::{
    find, get_features_from_registry, get_manifest_from_path, get_manifest_from_url, registry_url,
    workspace_members, Dependency,
};
use cargo_edit::{get_latest_dependency, CrateName};
use cargo_metadata::Package;
use clap::Parser;
use std::path::PathBuf;

use crate::errors::*;

#[derive(Debug, Parser)]
#[clap(bin_name = "cargo")]
pub enum Command {
    /// Add dependency to a Cargo.toml manifest file.
    #[clap(name = "add")]
    #[clap(after_help = "\
This command allows you to add a dependency to a Cargo.toml manifest file. If <crate> is a github \
or gitlab repository URL, or a local path, `cargo add` will try to automatically get the crate \
name and set the appropriate `--git` or `--path` value.

Please note that Cargo treats versions like '1.2.3' as '^1.2.3' (and that '^1.2.3' is specified \
as '>=1.2.3 and <2.0.0'). By default, `cargo add` will use this format, as it is the one that the \
crates.io registry suggests. One goal of `cargo add` is to prevent you from using wildcard \
dependencies (version set to '*').")]
    Add(Args),
}

#[derive(Debug, Parser)]
#[clap(about, version)]
pub struct Args {
    /// Crates to be added.
    #[clap(value_name = "CRATE", required = true)]
    pub crates: Vec<String>,

    /// Rename a dependency in Cargo.toml,
    /// https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml.
    /// Only works when specifying a single dependency.
    #[clap(long, short)]
    pub rename: Option<String>,

    /// Add crate as development dependency.
    #[clap(long, short = 'D', conflicts_with = "build")]
    pub dev: bool,

    /// Add crate as build dependency.
    #[clap(long, short = 'B', conflicts_with = "dev")]
    pub build: bool,

    /// Specify the version to grab from the registry(crates.io).
    /// You can also specify version as part of name, e.g
    /// `cargo add bitflags@0.3.2`.
    #[clap(long, value_name = "URI", conflicts_with = "git")]
    pub vers: Option<String>,

    /// Specify a git repository to download the crate from.
    #[clap(
        long,
        value_name = "URI",
        conflicts_with = "vers",
        conflicts_with = "path"
    )]
    pub git: Option<String>,

    /// Specify a git branch to download the crate from.
    #[clap(
        long,
        value_name = "BRANCH",
        conflicts_with = "vers",
        conflicts_with = "path"
    )]
    pub branch: Option<String>,

    /// Specify the path the crate should be loaded from.
    #[clap(long, parse(from_os_str), conflicts_with = "git")]
    pub path: Option<PathBuf>,

    /// Add as dependency to the given target platform.
    #[clap(
        long,
        conflicts_with = "dev",
        conflicts_with = "build",
        forbid_empty_values = true
    )]
    pub target: Option<String>,

    /// Add as an optional dependency (for use in features).
    #[clap(long, conflicts_with = "dev")]
    pub optional: bool,

    /// Path to the manifest to add a dependency to.
    #[clap(
        long,
        value_name = "PATH",
        parse(from_os_str),
        conflicts_with = "pkgid"
    )]
    pub manifest_path: Option<PathBuf>,

    /// Package id of the crate to add this dependency to.
    #[clap(
        long = "package",
        short = 'p',
        value_name = "PKGID",
        conflicts_with = "manifest-path"
    )]
    pub pkgid: Option<String>,

    /// Choose method of semantic version upgrade.  Must be one of "none" (exact version, `=`
    /// modifier), "patch" (`~` modifier), "minor" (`^` modifier), "all" (`>=`), or "default" (no
    /// modifier).
    #[clap(
        long,
        value_name = "METHOD",
        possible_value = "none",
        possible_value = "patch",
        possible_value = "minor",
        possible_value = "all",
        possible_value = "default",
        default_value = "default"
    )]
    pub upgrade: String,

    /// Include prerelease versions when fetching from crates.io (e.g.
    /// '0.6.0-alpha').
    #[clap(long)]
    pub allow_prerelease: bool,

    /// Space-separated list of features to add. For an alternative approach to
    /// enabling features, consider installing the `cargo-feature` utility.
    #[clap(long)]
    pub features: Option<Vec<String>>,

    /// Set `default-features = false` for the added dependency.
    #[clap(long)]
    pub no_default_features: bool,

    /// Do not print any output in case of success.
    #[clap(long)]
    pub quiet: bool,

    /// Run without accessing the network
    #[clap(long)]
    pub offline: bool,

    /// Sort dependencies even if currently unsorted
    #[clap(long, short)]
    pub sort: bool,

    /// Registry to use
    #[clap(long, conflicts_with = "git", conflicts_with = "path")]
    pub registry: Option<String>,
}

fn parse_version_req(s: &str) -> Result<&str> {
    semver::VersionReq::parse(s).chain_err(|| "Invalid dependency version requirement")?;
    Ok(s)
}

impl Args {
    /// Get dependency section
    pub fn get_section(&self) -> Vec<String> {
        if self.dev {
            vec!["dev-dependencies".to_owned()]
        } else if self.build {
            vec!["build-dependencies".to_owned()]
        } else if let Some(ref target) = self.target {
            assert!(!target.is_empty(), "Target specification may not be empty");

            vec![
                "target".to_owned(),
                target.clone(),
                "dependencies".to_owned(),
            ]
        } else {
            vec!["dependencies".to_owned()]
        }
    }

    fn parse_single_dependency(
        &self,
        crate_name: &str,
        workspace_members: &[Package],
    ) -> Result<Dependency> {
        let crate_name = CrateName::new(crate_name);
        let manifest_path = find(&self.manifest_path)?;
        let registry_url = registry_url(&manifest_path, self.registry.as_deref())?;

        let mut dependency = if let Some(mut dependency) = crate_name.parse_as_version()? {
            // crate specifier includes a version (e.g. `docopt@0.8`)
            if let Some(ref url) = self.git {
                let url = url.clone();
                let version = dependency.version().unwrap().to_string();
                return Err(ErrorKind::GitUrlWithVersion(url, version).into());
            }

            if let Some(ref path) = self.path {
                let manifest = get_manifest_from_path(path)?;
                let dep_path = dunce::canonicalize(path)?;

                dependency = dependency.set_available_features(manifest.features()?);
                dependency = dependency.set_path(dep_path);
            } else {
                let features = get_features_from_registry(
                    &dependency.name,
                    dependency
                        .version()
                        .expect("version populated by `parse_as_version`"),
                    &registry_url,
                )?;
                dependency = dependency.set_available_features(features);
            }

            dependency
        } else if let Some(mut dependency) = crate_name.parse_crate_name_from_uri()? {
            // dev-dependencies do not need the version populated
            if !self.dev {
                let dep_path = dependency.path().map(ToOwned::to_owned);
                if let Some(dep_path) = dep_path {
                    if let Some(package) = workspace_members.iter().find(|p| {
                        p.manifest_path.parent().map(|p| p.as_std_path())
                            == Some(dep_path.as_path())
                    }) {
                        let v = format!(
                            "{prefix}{version}",
                            prefix = self.get_upgrade_prefix(),
                            version = package.version
                        );

                        dependency = dependency.set_version(&v);
                    }
                }
            }
            dependency
        } else {
            let mut dependency = Dependency::new(crate_name.name());

            if let Some(repo) = &self.git {
                assert!(self.vers.is_none());
                assert!(self.path.is_none());
                assert!(self.registry.is_none());
                let features = get_manifest_from_url(repo)?
                    .map(|m| m.features())
                    .transpose()?
                    .unwrap_or_else(Vec::new);

                dependency = dependency
                    .set_git(repo, self.branch.clone())
                    .set_available_features(features);
            } else {
                if let Some(path) = &self.path {
                    assert!(self.registry.is_none());
                    let manifest = get_manifest_from_path(path)?;

                    dependency = dependency.set_available_features(manifest.features()?);
                    dependency = dependency.set_path(dunce::canonicalize(path)?);
                }
                if let Some(version) = &self.vers {
                    dependency = dependency.set_version(parse_version_req(version)?);
                }

                if self.git.is_none() && self.path.is_none() && self.vers.is_none() {
                    // Only special-case workspaces when the user doesn't provide any extra
                    // information, otherwise, trust the user.
                    if let Some(package) = workspace_members
                        .iter()
                        .find(|p| p.name == crate_name.name())
                    {
                        dependency = dependency.set_path(
                            package
                                .manifest_path
                                .parent()
                                .expect("at least parent dir")
                                .as_std_path()
                                .to_owned(),
                        );
                        // dev-dependencies do not need the version populated
                        if !self.dev {
                            let v = format!(
                                "{prefix}{version}",
                                prefix = self.get_upgrade_prefix(),
                                version = package.version
                            );
                            dependency = dependency.set_version(&v);
                        }
                    } else {
                        dependency = get_latest_dependency(
                            crate_name.name(),
                            self.allow_prerelease,
                            &manifest_path,
                            Some(&registry_url),
                        )?;
                        let v = format!(
                            "{prefix}{version}",
                            prefix = self.get_upgrade_prefix(),
                            // If version is unavailable `get_latest_dependency` must have
                            // returned `Err(FetchVersionError::GetVersion)`
                            version = dependency.version().unwrap_or_else(|| unreachable!())
                        );
                        dependency = dependency.set_version(&v);
                    }
                }
            }

            dependency
        };

        if let Some(registry) = &self.registry {
            dependency = dependency.set_registry(registry);
        }

        Ok(dependency)
    }

    /// Build dependencies from arguments
    pub fn parse_dependencies(
        &self,
        requested_features: Option<Vec<String>>,
    ) -> Result<Vec<Dependency>> {
        let workspace_members = workspace_members(self.manifest_path.as_deref())?;

        if self.crates.len() > 1
            && (self.git.is_some() || self.path.is_some() || self.vers.is_some())
        {
            return Err(ErrorKind::MultipleCratesWithGitOrPathOrVers.into());
        }

        if self.crates.len() > 1 && self.rename.is_some() {
            return Err(ErrorKind::MultipleCratesWithRename.into());
        }

        if self.crates.len() > 1 && self.features.is_some() {
            return Err(ErrorKind::MultipleCratesWithFeatures.into());
        }

        self.crates
            .iter()
            .map(|crate_name| {
                self.parse_single_dependency(crate_name, &workspace_members)
                    .map(|x| {
                        let mut x = x
                            .set_optional(self.optional)
                            .set_features(requested_features.to_owned())
                            .set_default_features(!self.no_default_features);
                        if let Some(ref rename) = self.rename {
                            x = x.set_rename(rename);
                        }
                        x
                    })
            })
            .collect()
    }

    fn get_upgrade_prefix(&self) -> &'static str {
        match self.upgrade.as_ref() {
            "default" => "",
            "none" => "=",
            "patch" => "~",
            "minor" => "^",
            "all" => ">=",
            _ => unreachable!(),
        }
    }
}

#[cfg(test)]
impl Default for Args {
    fn default() -> Args {
        Args {
            crates: vec!["demo".to_owned()],
            rename: None,
            dev: false,
            build: false,
            vers: None,
            git: None,
            branch: None,
            path: None,
            target: None,
            optional: false,
            manifest_path: None,
            pkgid: None,
            upgrade: "minor".to_string(),
            allow_prerelease: false,
            features: None,
            no_default_features: false,
            quiet: false,
            offline: true,
            sort: false,
            registry: None,
        }
    }
}

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

    #[test]
    fn test_dependency_parsing() {
        let args = Args {
            vers: Some("0.4.2".to_owned()),
            ..Args::default()
        };

        assert_eq!(
            args.parse_dependencies(None).unwrap(),
            vec![Dependency::new("demo").set_version("0.4.2")]
        );
    }

    #[test]
    #[cfg(feature = "test-external-apis")]
    fn test_repo_as_arg_parsing() {
        let github_url = "https://github.com/killercup/cargo-edit/";
        let args_github = Args {
            crates: vec![github_url.to_owned()],
            ..Args::default()
        };
        assert_eq!(
            args_github.parse_dependencies(None).unwrap(),
            vec![Dependency::new("cargo-edit").set_git(github_url, None)]
        );

        let gitlab_url = "https://gitlab.com/Polly-lang/Polly.git";
        let args_gitlab = Args {
            crates: vec![gitlab_url.to_owned()],
            ..Args::default()
        };
        assert_eq!(
            args_gitlab.parse_dependencies(None).unwrap(),
            vec![Dependency::new("polly").set_git(gitlab_url, None)]
        );
    }

    #[test]
    fn test_path_as_arg_parsing() {
        let self_path = dunce::canonicalize(std::env::current_dir().unwrap()).unwrap();
        let args_path = Args {
            // Hacky to `display` but should generally work
            crates: vec![self_path.display().to_string()],
            ..Args::default()
        };
        assert_eq!(
            args_path.parse_dependencies(None).unwrap()[0]
                .path()
                .unwrap(),
            self_path
        );
    }

    #[test]
    fn verify_app() {
        use clap::IntoApp;
        Command::into_app().debug_assert()
    }
}
<commit_msg>refactor(add): Clean up arg relationships<commit_after>//! Handle `cargo add` arguments

#![allow(clippy::bool_assert_comparison)]

use cargo_edit::{
    find, get_features_from_registry, get_manifest_from_path, get_manifest_from_url, registry_url,
    workspace_members, Dependency,
};
use cargo_edit::{get_latest_dependency, CrateName};
use cargo_metadata::Package;
use clap::Parser;
use std::path::PathBuf;

use crate::errors::*;

#[derive(Debug, Parser)]
#[clap(bin_name = "cargo")]
pub enum Command {
    /// Add dependency to a Cargo.toml manifest file.
    #[clap(name = "add")]
    #[clap(after_help = "\
This command allows you to add a dependency to a Cargo.toml manifest file. If <crate> is a github \
or gitlab repository URL, or a local path, `cargo add` will try to automatically get the crate \
name and set the appropriate `--git` or `--path` value.

Please note that Cargo treats versions like '1.2.3' as '^1.2.3' (and that '^1.2.3' is specified \
as '>=1.2.3 and <2.0.0'). By default, `cargo add` will use this format, as it is the one that the \
crates.io registry suggests. One goal of `cargo add` is to prevent you from using wildcard \
dependencies (version set to '*').")]
    Add(Args),
}

#[derive(Debug, Parser)]
#[clap(about, version)]
pub struct Args {
    /// Crates to be added.
    #[clap(value_name = "CRATE", required = true)]
    pub crates: Vec<String>,

    /// Rename a dependency in Cargo.toml,
    /// https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml.
    /// Only works when specifying a single dependency.
    #[clap(long, short)]
    pub rename: Option<String>,

    /// Add crate as development dependency.
    #[clap(long, short = 'D', group = "section")]
    pub dev: bool,

    /// Add crate as build dependency.
    #[clap(long, short = 'B', group = "section")]
    pub build: bool,

    /// Add as dependency to the given target platform.
    #[clap(long, forbid_empty_values = true, group = "section")]
    pub target: Option<String>,

    /// Specify the version to grab from the registry(crates.io).
    /// You can also specify version as part of name, e.g
    /// `cargo add bitflags@0.3.2`.
    #[clap(long, value_name = "URI", conflicts_with = "git")]
    pub vers: Option<String>,

    /// Specify a git repository to download the crate from.
    #[clap(
        long,
        value_name = "URI",
        conflicts_with = "vers",
        conflicts_with = "path"
    )]
    pub git: Option<String>,

    /// Specify a git branch to download the crate from.
    #[clap(long, value_name = "BRANCH", requires = "git")]
    pub branch: Option<String>,

    /// Specify the path the crate should be loaded from.
    #[clap(long, parse(from_os_str), conflicts_with = "git")]
    pub path: Option<PathBuf>,

    /// Add as an optional dependency (for use in features).
    #[clap(long, conflicts_with = "dev")]
    pub optional: bool,

    /// Path to the manifest to add a dependency to.
    #[clap(
        long,
        value_name = "PATH",
        parse(from_os_str),
        conflicts_with = "pkgid"
    )]
    pub manifest_path: Option<PathBuf>,

    /// Package id of the crate to add this dependency to.
    #[clap(
        long = "package",
        short = 'p',
        value_name = "PKGID",
        conflicts_with = "manifest-path"
    )]
    pub pkgid: Option<String>,

    /// Choose method of semantic version upgrade.  Must be one of "none" (exact version, `=`
    /// modifier), "patch" (`~` modifier), "minor" (`^` modifier), "all" (`>=`), or "default" (no
    /// modifier).
    #[clap(
        long,
        value_name = "METHOD",
        possible_value = "none",
        possible_value = "patch",
        possible_value = "minor",
        possible_value = "all",
        possible_value = "default",
        default_value = "default"
    )]
    pub upgrade: String,

    /// Include prerelease versions when fetching from crates.io (e.g.
    /// '0.6.0-alpha').
    #[clap(long)]
    pub allow_prerelease: bool,

    /// Space-separated list of features to add. For an alternative approach to
    /// enabling features, consider installing the `cargo-feature` utility.
    #[clap(long)]
    pub features: Option<Vec<String>>,

    /// Set `default-features = false` for the added dependency.
    #[clap(long)]
    pub no_default_features: bool,

    /// Do not print any output in case of success.
    #[clap(long)]
    pub quiet: bool,

    /// Run without accessing the network
    #[clap(long)]
    pub offline: bool,

    /// Sort dependencies even if currently unsorted
    #[clap(long, short)]
    pub sort: bool,

    /// Registry to use
    #[clap(long, conflicts_with = "git", conflicts_with = "path")]
    pub registry: Option<String>,
}

fn parse_version_req(s: &str) -> Result<&str> {
    semver::VersionReq::parse(s).chain_err(|| "Invalid dependency version requirement")?;
    Ok(s)
}

impl Args {
    /// Get dependency section
    pub fn get_section(&self) -> Vec<String> {
        if self.dev {
            vec!["dev-dependencies".to_owned()]
        } else if self.build {
            vec!["build-dependencies".to_owned()]
        } else if let Some(ref target) = self.target {
            assert!(!target.is_empty(), "Target specification may not be empty");

            vec![
                "target".to_owned(),
                target.clone(),
                "dependencies".to_owned(),
            ]
        } else {
            vec!["dependencies".to_owned()]
        }
    }

    fn parse_single_dependency(
        &self,
        crate_name: &str,
        workspace_members: &[Package],
    ) -> Result<Dependency> {
        let crate_name = CrateName::new(crate_name);
        let manifest_path = find(&self.manifest_path)?;
        let registry_url = registry_url(&manifest_path, self.registry.as_deref())?;

        let mut dependency = if let Some(mut dependency) = crate_name.parse_as_version()? {
            // crate specifier includes a version (e.g. `docopt@0.8`)
            if let Some(ref url) = self.git {
                let url = url.clone();
                let version = dependency.version().unwrap().to_string();
                return Err(ErrorKind::GitUrlWithVersion(url, version).into());
            }

            if let Some(ref path) = self.path {
                let manifest = get_manifest_from_path(path)?;
                let dep_path = dunce::canonicalize(path)?;

                dependency = dependency.set_available_features(manifest.features()?);
                dependency = dependency.set_path(dep_path);
            } else {
                let features = get_features_from_registry(
                    &dependency.name,
                    dependency
                        .version()
                        .expect("version populated by `parse_as_version`"),
                    &registry_url,
                )?;
                dependency = dependency.set_available_features(features);
            }

            dependency
        } else if let Some(mut dependency) = crate_name.parse_crate_name_from_uri()? {
            // dev-dependencies do not need the version populated
            if !self.dev {
                let dep_path = dependency.path().map(ToOwned::to_owned);
                if let Some(dep_path) = dep_path {
                    if let Some(package) = workspace_members.iter().find(|p| {
                        p.manifest_path.parent().map(|p| p.as_std_path())
                            == Some(dep_path.as_path())
                    }) {
                        let v = format!(
                            "{prefix}{version}",
                            prefix = self.get_upgrade_prefix(),
                            version = package.version
                        );

                        dependency = dependency.set_version(&v);
                    }
                }
            }
            dependency
        } else {
            let mut dependency = Dependency::new(crate_name.name());

            if let Some(repo) = &self.git {
                assert!(self.vers.is_none());
                assert!(self.path.is_none());
                assert!(self.registry.is_none());
                let features = get_manifest_from_url(repo)?
                    .map(|m| m.features())
                    .transpose()?
                    .unwrap_or_else(Vec::new);

                dependency = dependency
                    .set_git(repo, self.branch.clone())
                    .set_available_features(features);
            } else {
                if let Some(path) = &self.path {
                    assert!(self.registry.is_none());
                    let manifest = get_manifest_from_path(path)?;

                    dependency = dependency.set_available_features(manifest.features()?);
                    dependency = dependency.set_path(dunce::canonicalize(path)?);
                }
                if let Some(version) = &self.vers {
                    dependency = dependency.set_version(parse_version_req(version)?);
                }

                if self.git.is_none() && self.path.is_none() && self.vers.is_none() {
                    // Only special-case workspaces when the user doesn't provide any extra
                    // information, otherwise, trust the user.
                    if let Some(package) = workspace_members
                        .iter()
                        .find(|p| p.name == crate_name.name())
                    {
                        dependency = dependency.set_path(
                            package
                                .manifest_path
                                .parent()
                                .expect("at least parent dir")
                                .as_std_path()
                                .to_owned(),
                        );
                        // dev-dependencies do not need the version populated
                        if !self.dev {
                            let v = format!(
                                "{prefix}{version}",
                                prefix = self.get_upgrade_prefix(),
                                version = package.version
                            );
                            dependency = dependency.set_version(&v);
                        }
                    } else {
                        dependency = get_latest_dependency(
                            crate_name.name(),
                            self.allow_prerelease,
                            &manifest_path,
                            Some(&registry_url),
                        )?;
                        let v = format!(
                            "{prefix}{version}",
                            prefix = self.get_upgrade_prefix(),
                            // If version is unavailable `get_latest_dependency` must have
                            // returned `Err(FetchVersionError::GetVersion)`
                            version = dependency.version().unwrap_or_else(|| unreachable!())
                        );
                        dependency = dependency.set_version(&v);
                    }
                }
            }

            dependency
        };

        if let Some(registry) = &self.registry {
            dependency = dependency.set_registry(registry);
        }

        Ok(dependency)
    }

    /// Build dependencies from arguments
    pub fn parse_dependencies(
        &self,
        requested_features: Option<Vec<String>>,
    ) -> Result<Vec<Dependency>> {
        let workspace_members = workspace_members(self.manifest_path.as_deref())?;

        if self.crates.len() > 1
            && (self.git.is_some() || self.path.is_some() || self.vers.is_some())
        {
            return Err(ErrorKind::MultipleCratesWithGitOrPathOrVers.into());
        }

        if self.crates.len() > 1 && self.rename.is_some() {
            return Err(ErrorKind::MultipleCratesWithRename.into());
        }

        if self.crates.len() > 1 && self.features.is_some() {
            return Err(ErrorKind::MultipleCratesWithFeatures.into());
        }

        self.crates
            .iter()
            .map(|crate_name| {
                self.parse_single_dependency(crate_name, &workspace_members)
                    .map(|x| {
                        let mut x = x
                            .set_optional(self.optional)
                            .set_features(requested_features.to_owned())
                            .set_default_features(!self.no_default_features);
                        if let Some(ref rename) = self.rename {
                            x = x.set_rename(rename);
                        }
                        x
                    })
            })
            .collect()
    }

    fn get_upgrade_prefix(&self) -> &'static str {
        match self.upgrade.as_ref() {
            "default" => "",
            "none" => "=",
            "patch" => "~",
            "minor" => "^",
            "all" => ">=",
            _ => unreachable!(),
        }
    }
}

#[cfg(test)]
impl Default for Args {
    fn default() -> Args {
        Args {
            crates: vec!["demo".to_owned()],
            rename: None,
            dev: false,
            build: false,
            vers: None,
            git: None,
            branch: None,
            path: None,
            target: None,
            optional: false,
            manifest_path: None,
            pkgid: None,
            upgrade: "minor".to_string(),
            allow_prerelease: false,
            features: None,
            no_default_features: false,
            quiet: false,
            offline: true,
            sort: false,
            registry: None,
        }
    }
}

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

    #[test]
    fn test_dependency_parsing() {
        let args = Args {
            vers: Some("0.4.2".to_owned()),
            ..Args::default()
        };

        assert_eq!(
            args.parse_dependencies(None).unwrap(),
            vec![Dependency::new("demo").set_version("0.4.2")]
        );
    }

    #[test]
    #[cfg(feature = "test-external-apis")]
    fn test_repo_as_arg_parsing() {
        let github_url = "https://github.com/killercup/cargo-edit/";
        let args_github = Args {
            crates: vec![github_url.to_owned()],
            ..Args::default()
        };
        assert_eq!(
            args_github.parse_dependencies(None).unwrap(),
            vec![Dependency::new("cargo-edit").set_git(github_url, None)]
        );

        let gitlab_url = "https://gitlab.com/Polly-lang/Polly.git";
        let args_gitlab = Args {
            crates: vec![gitlab_url.to_owned()],
            ..Args::default()
        };
        assert_eq!(
            args_gitlab.parse_dependencies(None).unwrap(),
            vec![Dependency::new("polly").set_git(gitlab_url, None)]
        );
    }

    #[test]
    fn test_path_as_arg_parsing() {
        let self_path = dunce::canonicalize(std::env::current_dir().unwrap()).unwrap();
        let args_path = Args {
            // Hacky to `display` but should generally work
            crates: vec![self_path.display().to_string()],
            ..Args::default()
        };
        assert_eq!(
            args_path.parse_dependencies(None).unwrap()[0]
                .path()
                .unwrap(),
            self_path
        );
    }

    #[test]
    fn verify_app() {
        use clap::IntoApp;
        Command::into_app().debug_assert()
    }
}
<|endoftext|>


<commit_before>use prodbg_api::view::CViewCallbacks;
use libc::{c_void, c_uchar};
use std::rc::Rc;
use plugin::Plugin;
use plugins::PluginHandler;
use dynamic_reload::Lib;
use session::SessionHandle;
use std::ptr;
use prodbg_api::ui::Ui;
use plugin_io;

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct ViewHandle(pub u64);

pub struct ViewInstance {
    pub plugin_data: *mut c_void,
    pub ui: Ui,
    pub name: String,
    pub handle: ViewHandle,
    pub session_handle: SessionHandle,
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
    pub plugin_type: Rc<Plugin>,
}

#[derive(Clone)]
struct ReloadState {
    name: String,
    ui: Ui,
    handle: ViewHandle,
    session_handle: SessionHandle,
}

pub struct ViewPlugins {
    pub instances: Vec<ViewInstance>,
    plugin_types: Vec<Rc<Plugin>>,
    reload_state: Vec<ReloadState>,
    handle_counter: ViewHandle,
}

impl PluginHandler for ViewPlugins {
    fn is_correct_plugin_type(&self, plugin: &Plugin) -> bool {
        plugin.type_name.contains("View")
    }

    fn add_plugin(&mut self, plugin: &Rc<Plugin>) {
        println!("added plugin type {}", plugin.type_name);
        self.plugin_types.push(plugin.clone())
    }

    fn unload_plugin(&mut self, lib: &Rc<Lib>) {
        self.reload_state.clear();
        for i in (0..self.instances.len()).rev() {
            if &self.instances[i].plugin_type.lib == lib {
                let state = ReloadState {
                    ui: self.instances[i].ui.clone(),
                    name: self.instances[i].plugin_type.name.clone(),
                    handle: self.instances[i].handle,
                    session_handle: self.instances[i].session_handle,
                };

                self.reload_state.push(state);
                self.instances.swap_remove(i);
            }
        }

        for i in (0..self.plugin_types.len()).rev() {
            if &self.plugin_types[i].lib == lib {
                self.plugin_types.swap_remove(i);
            }
        }
    }

    fn reload_plugin(&mut self) {
        let t = self.reload_state.clone();
        for reload_plugin in &t {
            Self::create_instance(self,
                                  reload_plugin.ui.clone(),
                                  &reload_plugin.name,
                                  reload_plugin.session_handle);
        }
    }

    fn reload_failed(&mut self) {}
}

impl ViewPlugins {
    pub fn new() -> ViewPlugins {
        ViewPlugins {
            instances: Vec::new(),
            plugin_types: Vec::new(),
            reload_state: Vec::new(),
            handle_counter: ViewHandle(0),
        }
    }

    pub extern "C" fn service_fun(_name: *const c_uchar) -> *mut c_void {
        ptr::null_mut()
    }

    pub fn get_view(&mut self, view_handle: ViewHandle) -> Option<&mut ViewInstance> {
        for i in 0..self.instances.len() {
            if self.instances[i].handle == view_handle {
                return Some(&mut self.instances[i]);
            }
        }

        None
    }

    pub fn create_instance_from_index(&mut self,
                                      ui: Ui,
                                      index: usize,
                                      session_handle: SessionHandle,
                                      view_handle: Option<ViewHandle>)
                                      -> Option<ViewHandle> {
        let plugin_data = unsafe {
            let callbacks = self.plugin_types[index].plugin_funcs as *mut CViewCallbacks;
            (*callbacks).create_instance.unwrap()(ui.api as *mut c_void, Self::service_fun)
        };

        let handle = match view_handle {
            Some(h) => {
                if h.0 >= self.handle_counter.0 {
                    self.handle_counter.0 = h.0 + 1
                }
                h
            },
            _ => {
                let counter = self.handle_counter;
                self.handle_counter.0 += 1;
                counter
            }
        };

        let instance = ViewInstance {
            plugin_data: plugin_data,
            name: format!("Plugin {}", handle.0),
            ui: ui,
            handle: handle,
            session_handle: session_handle,
            x: 0.0,
            y: 0.0,
            width: 0.0,
            height: 0.0,
            plugin_type: self.plugin_types[index].clone(),
        };

        self.instances.push(instance);

        Some(handle)
    }

    pub fn create_instance(&mut self,
                           ui: Ui,
                           plugin_type: &String,
                           session_handle: SessionHandle)
                           -> Option<ViewHandle> {
        for i in 0..self.plugin_types.len() {
            if self.plugin_types[i].name != *plugin_type {
                continue;
            }

            return Self::create_instance_from_index(self, ui, i, session_handle, None);
        }

        None
    }

    pub fn create_instance_with_handle(&mut self,
                                       ui: Ui,
                                       plugin_type: &String,
                                       plugin_data: &Option<Vec<String>>,
                                       session_handle: SessionHandle,
                                       view_handle: ViewHandle) -> Option<ViewHandle> {

        for i in 0..self.plugin_types.len() {
            if self.plugin_types[i].name != *plugin_type {
                continue;
            }

            let handle = Self::create_instance_from_index(self, ui, i, session_handle, Some(view_handle));

            if let Some(ref data) = *plugin_data {
                self.get_view(handle.unwrap()).map(|instance| {
                    instance.load_plugin_data(&data);
                });
            }

            return handle;
        }

        None
    }

    pub fn destroy_instance(&mut self, handle: ViewHandle) {
        for i in (0..self.instances.len()).rev() {
            if self.instances[i].handle.0 == handle.0 {
                self.instances.swap_remove(i);
                return;
            }
        }
    }

    // TODO: Would be nice to use something stack-base instead or return an iterator to interate
    // over the data instead
    pub fn get_plugin_names(&self) -> Vec<String> {
        let mut names = Vec::new();

        for i in &self.plugin_types {
            names.push(i.name.clone());
        }

        names
    }
}

impl ViewInstance {
    pub fn get_plugin_data(&self) -> (String, Option<Vec<String>>) {
        let mut plugin_data = None;
        unsafe {
            let callbacks = self.plugin_type.plugin_funcs as *mut CViewCallbacks;
            if let Some(save_state) = (*callbacks).save_state {
                let mut writer_funcs = plugin_io::get_writer_funcs();
                save_state(self.plugin_data, &mut writer_funcs);
                plugin_data = Some(plugin_io::get_data(&mut writer_funcs));
            }
        };
        (self.plugin_type.name.clone(), plugin_data)
    }

    pub fn load_plugin_data(&mut self, data: &Vec<String>) {
        unsafe {
            let callbacks = self.plugin_type.plugin_funcs as *mut CViewCallbacks;
            if let Some(load_state) = (*callbacks).load_state {
                let mut loader_funcs = plugin_io::get_loader_funcs(data);
                load_state(self.plugin_data, &mut loader_funcs);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_search_paths_none() {}
}
<commit_msg>Fixed reloading of plugins<commit_after>use prodbg_api::view::CViewCallbacks;
use libc::{c_void, c_uchar};
use std::rc::Rc;
use plugin::Plugin;
use plugins::PluginHandler;
use dynamic_reload::Lib;
use session::SessionHandle;
use std::ptr;
use prodbg_api::ui::Ui;
use plugin_io;

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct ViewHandle(pub u64);

pub struct ViewInstance {
    pub plugin_data: *mut c_void,
    pub ui: Ui,
    pub name: String,
    pub handle: ViewHandle,
    pub session_handle: SessionHandle,
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
    pub plugin_type: Rc<Plugin>,
}

#[derive(Clone)]
struct ReloadState {
    name: String,
    ui: Ui,
    handle: ViewHandle,
    session_handle: SessionHandle,
}

pub struct ViewPlugins {
    pub instances: Vec<ViewInstance>,
    plugin_types: Vec<Rc<Plugin>>,
    reload_state: Vec<ReloadState>,
    handle_counter: ViewHandle,
}

impl PluginHandler for ViewPlugins {
    fn is_correct_plugin_type(&self, plugin: &Plugin) -> bool {
        plugin.type_name.contains("View")
    }

    fn add_plugin(&mut self, plugin: &Rc<Plugin>) {
        println!("added plugin type {}", plugin.type_name);
        self.plugin_types.push(plugin.clone())
    }

    fn unload_plugin(&mut self, lib: &Rc<Lib>) {
        self.reload_state.clear();
        for i in (0..self.instances.len()).rev() {
            if &self.instances[i].plugin_type.lib == lib {
                let state = ReloadState {
                    ui: self.instances[i].ui.clone(),
                    name: self.instances[i].plugin_type.name.clone(),
                    handle: self.instances[i].handle,
                    session_handle: self.instances[i].session_handle,
                };

                self.reload_state.push(state);
                self.instances.swap_remove(i);
            }
        }

        for i in (0..self.plugin_types.len()).rev() {
            if &self.plugin_types[i].lib == lib {
                self.plugin_types.swap_remove(i);
            }
        }
    }

    fn reload_plugin(&mut self) {
        let t = self.reload_state.clone();
        for reload_plugin in &t {
            self.create_instance_with_handle(
                                  reload_plugin.ui.clone(),
                                  &reload_plugin.name,
                                  &None, // TODO: Include saved data here
                                  reload_plugin.session_handle,
                                  reload_plugin.handle);
        }
    }

    fn reload_failed(&mut self) {}
}

impl ViewPlugins {
    pub fn new() -> ViewPlugins {
        ViewPlugins {
            instances: Vec::new(),
            plugin_types: Vec::new(),
            reload_state: Vec::new(),
            handle_counter: ViewHandle(0),
        }
    }

    pub extern "C" fn service_fun(_name: *const c_uchar) -> *mut c_void {
        ptr::null_mut()
    }

    pub fn get_view(&mut self, view_handle: ViewHandle) -> Option<&mut ViewInstance> {
        for i in 0..self.instances.len() {
            if self.instances[i].handle == view_handle {
                return Some(&mut self.instances[i]);
            }
        }

        None
    }

    pub fn create_instance_from_index(&mut self,
                                      ui: Ui,
                                      index: usize,
                                      session_handle: SessionHandle,
                                      view_handle: Option<ViewHandle>)
                                      -> Option<ViewHandle> {
        let plugin_data = unsafe {
            let callbacks = self.plugin_types[index].plugin_funcs as *mut CViewCallbacks;
            (*callbacks).create_instance.unwrap()(ui.api as *mut c_void, Self::service_fun)
        };

        let handle = match view_handle {
            Some(h) => {
                if h.0 >= self.handle_counter.0 {
                    self.handle_counter.0 = h.0 + 1
                }
                h
            },
            _ => {
                let counter = self.handle_counter;
                self.handle_counter.0 += 1;
                counter
            }
        };

        let instance = ViewInstance {
            plugin_data: plugin_data,
            name: format!("Plugin {}", handle.0),
            ui: ui,
            handle: handle,
            session_handle: session_handle,
            x: 0.0,
            y: 0.0,
            width: 0.0,
            height: 0.0,
            plugin_type: self.plugin_types[index].clone(),
        };

        self.instances.push(instance);

        Some(handle)
    }

    pub fn create_instance(&mut self,
                           ui: Ui,
                           plugin_type: &String,
                           session_handle: SessionHandle)
                           -> Option<ViewHandle> {
        for i in 0..self.plugin_types.len() {
            if self.plugin_types[i].name != *plugin_type {
                continue;
            }

            return Self::create_instance_from_index(self, ui, i, session_handle, None);
        }

        None
    }

    pub fn create_instance_with_handle(&mut self,
                                       ui: Ui,
                                       plugin_type: &String,
                                       plugin_data: &Option<Vec<String>>,
                                       session_handle: SessionHandle,
                                       view_handle: ViewHandle) -> Option<ViewHandle> {

        for i in 0..self.plugin_types.len() {
            if self.plugin_types[i].name != *plugin_type {
                continue;
            }

            let handle = Self::create_instance_from_index(self, ui, i, session_handle, Some(view_handle));

            if let Some(ref data) = *plugin_data {
                self.get_view(handle.unwrap()).map(|instance| {
                    instance.load_plugin_data(&data);
                });
            }

            return handle;
        }

        None
    }

    pub fn destroy_instance(&mut self, handle: ViewHandle) {
        for i in (0..self.instances.len()).rev() {
            if self.instances[i].handle.0 == handle.0 {
                self.instances.swap_remove(i);
                return;
            }
        }
    }

    // TODO: Would be nice to use something stack-base instead or return an iterator to interate
    // over the data instead
    pub fn get_plugin_names(&self) -> Vec<String> {
        let mut names = Vec::new();

        for i in &self.plugin_types {
            names.push(i.name.clone());
        }

        names
    }
}

impl ViewInstance {
    pub fn get_plugin_data(&self) -> (String, Option<Vec<String>>) {
        let mut plugin_data = None;
        unsafe {
            let callbacks = self.plugin_type.plugin_funcs as *mut CViewCallbacks;
            if let Some(save_state) = (*callbacks).save_state {
                let mut writer_funcs = plugin_io::get_writer_funcs();
                save_state(self.plugin_data, &mut writer_funcs);
                plugin_data = Some(plugin_io::get_data(&mut writer_funcs));
            }
        };
        (self.plugin_type.name.clone(), plugin_data)
    }

    pub fn load_plugin_data(&mut self, data: &Vec<String>) {
        unsafe {
            let callbacks = self.plugin_type.plugin_funcs as *mut CViewCallbacks;
            if let Some(load_state) = (*callbacks).load_state {
                let mut loader_funcs = plugin_io::get_loader_funcs(data);
                load_state(self.plugin_data, &mut loader_funcs);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_search_paths_none() {}
}
<|endoftext|>


<commit_before>use std::cmp::{max, min};
use std::fmt;
use std::slice::Iter;

#[derive(Copy, Clone)]
pub struct Range {
    pub start: usize,
    pub length: usize,
}

impl fmt::Display for Range {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        return write!(f, "[{}, {}]", self.start, self.start + self.length - 1);
    }
}

impl Range {
    pub fn new(start: usize, length: usize) -> Range {
        return Range {
            start: start,
            length: length,
        };
    }

    pub fn end(&self) -> usize {
        return self.start + self.length;
    }
}

#[derive(Clone)]
pub struct RangeSet {
    ranges: Vec<Range>,
}

impl fmt::Display for RangeSet {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "(").unwrap();
        for range in self.ranges.iter() {
            write!(f, "{}", range).unwrap();
        }
        write!(f, ")")
    }
}

impl RangeSet {
    pub fn new() -> RangeSet {
        RangeSet {
            ranges: Vec::<Range>::new(),
        }
    }

    pub fn is_empty(&self) -> bool {
        return self.ranges.is_empty();
    }

    pub fn len(&self) -> usize {
        let mut result = 0;
        for range in self.ranges.iter() {
            result += range.length;
        }
        return result;
    }

    pub fn get_range(&self, index: usize) -> Range {
        return self.ranges[index].clone();
    }

    pub fn iter(&self) -> Iter<Range> {
        return self.ranges.iter();
    }

    pub fn contains(&self, value: usize) -> bool {
        for range in self.ranges.iter() {
            if value < range.start {
                return false;
            } else if range.start <= value && value < range.end() {
                return true;
            }
        }
        return false;
    }

    pub fn contained_length_from_value(&self, value: usize) -> usize {
        for range in self.ranges.iter() {
            if value < range.start {
                return 0;
            } else if range.start <= value && value < range.end() {
                return range.end() - value;
            }
        }
        return 0;
    }

    #[allow(dead_code)]
    pub fn contains_range_set(&self, other: &RangeSet) -> bool {
        for range in other.ranges.iter() {
            if self.contained_length_from_value(range.start) < range.length {
                return false;
            }
        }
        return true;
    }

    pub fn add_range(&mut self, range: &Range) {
        if range.length <= 0 {
            // the interval is empty or invalid -> nothing to do.
            return;
        }

        for index in 0..self.ranges.len() {
            // the new range is clear of any ranges we already iterated over.
            if range.end() < self.ranges[index].start {
                // the new range starts after anything we already passed and ends before the next range starts (they don't touch) -> insert it.
                self.ranges.insert(index, range.clone());
                return;
            } else if range.start <= self.ranges[index].end()
                && self.ranges[index].start <= range.end()
            {
                // the new range overlaps (or touches) the first range. They are to be merged.
                // In addition we might have to merge further ranges in as well.

                let mut new_range = range.clone();

                while index < self.ranges.len() && self.ranges[index].start <= new_range.end() {
                    let new_end = max(new_range.end(), self.ranges[index].end());
                    new_range.start = min(new_range.start, self.ranges[index].start);
                    new_range.length = new_end - new_range.start;
                    self.ranges.remove(index);
                }

                self.ranges.insert(index, new_range);
                return;
            }
        }

        // the new range is after everything else -> just add it
        self.ranges.push(range.clone());
    }

    #[allow(dead_code)]
    pub fn add_range_set(&mut self, other: &RangeSet) {
        for range in other.ranges.iter() {
            self.add_range(range);
        }
    }

    #[allow(dead_code)]
    pub fn union(&self, other: &RangeSet) -> RangeSet {
        let mut result = self.clone();
        result.add_range_set(other);
        return result;
    }

    pub fn subtract_range(&mut self, range: &Range) {
        if range.length <= 0 {
            return;
        }

        for index in 0..self.ranges.len() {
            // the ranges we already passed don't overlap with the range to remove

            if range.end() <= self.ranges[index].start {
                // the remaining ranges are past the one to subtract. -> we're done.
                return;
            } else if range.start <= self.ranges[index].start
                && self.ranges[index].start < range.end()
            {
                // the range to subtract started before the current range and reaches into the current range
                // -> we have to remove the beginning of the range or the entire range and do the same for following ranges.

                while index < self.ranges.len() && self.ranges[index].end() <= range.end() {
                    self.ranges.remove(index);
                }

                if index < self.ranges.len() && self.ranges[index].start < range.end() {
                    self.ranges[index].length -= range.end() - self.ranges[index].start;
                    self.ranges[index].start = range.end();
                }

                return;
            } else if range.end() < self.ranges[index].end() {
                // the range to subtract punches a hole into the current range -> we need to create two smaller ranges.

                let first_range = Range {
                    start: self.ranges[index].start,
                    length: range.start - self.ranges[index].start,
                };

                self.ranges[index].length -= range.end() - self.ranges[index].start;
                self.ranges[index].start = range.end();

                self.ranges.insert(index, first_range);

                return;
            } else if range.start < self.ranges[index].end() {
                // the range truncates the existing range -> truncate the range. Let the for loop take care of overlaps with other ranges.
                self.ranges[index].length = range.start - self.ranges[index].start;
            }
        }
    }

    pub fn subtract_range_set(&mut self, other: &RangeSet) {
        for range in other.ranges.iter() {
            self.subtract_range(range);
        }
    }

    pub fn minus(&self, other: &RangeSet) -> RangeSet {
        let mut result = self.clone();
        result.subtract_range_set(other);
        return result;
    }

    pub fn intersection(&self, other: &RangeSet) -> RangeSet {
        let mut result = RangeSet::new();

        let mut self_index: usize = 0;
        let mut other_index: usize = 0;

        while self_index < self.ranges.len() && other_index < other.ranges.len() {
            if self.ranges[self_index].end() <= other.ranges[other_index].start {
                // skip the interval
                self_index += 1;
            } else if other.ranges[other_index].end() <= self.ranges[self_index].start {
                // skip the interval
                other_index += 1;
            } else {
                // the two intervals overlap. Add the union and advance the index of the one that ends first.
                let new_start = max(
                    self.ranges[self_index].start,
                    other.ranges[other_index].start,
                );
                let new_end = min(
                    self.ranges[self_index].end(),
                    other.ranges[other_index].end(),
                );
                assert!(new_start <= new_end);
                result.add_range(&Range::new(new_start, new_end - new_start));
                if self.ranges[self_index].end() <= other.ranges[other_index].end() {
                    self_index += 1;
                } else {
                    other_index += 1;
                }
            }
        }

        return result;
    }
}
<commit_msg>Improved RangeSet implementation<commit_after>use std::cmp::{max, min};
use std::fmt;
use std::slice::Iter;

#[derive(Copy, Clone)]
pub struct Range {
    pub start: usize,
    pub length: usize,
}

impl fmt::Display for Range {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        return write!(f, "[{}, {}]", self.start, self.start + self.length - 1);
    }
}

impl Range {
    pub fn new(start: usize, length: usize) -> Range {
        return Range {
            start: start,
            length: length,
        };
    }

    pub fn end(&self) -> usize {
        return self.start + self.length;
    }
}

#[derive(Clone)]
pub struct RangeSet {
    ranges: Vec<Range>,
}

impl fmt::Display for RangeSet {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "(").unwrap();
        for range in self.ranges.iter() {
            write!(f, "{}", range).unwrap();
        }
        write!(f, ")")
    }
}

impl RangeSet {
    pub fn new() -> RangeSet {
        RangeSet {
            ranges: Vec::<Range>::new(),
        }
    }

    pub fn is_empty(&self) -> bool {
        return self.ranges.is_empty();
    }

    pub fn len(&self) -> usize {
        self.ranges.iter().map(|r| r.length).fold(0, std::ops::Add::add)
    }

    pub fn get_range(&self, index: usize) -> Range {
        return self.ranges[index].clone();
    }

    pub fn iter(&self) -> Iter<Range> {
        return self.ranges.iter();
    }

    pub fn contains(&self, value: usize) -> bool {
        for range in self.ranges.iter() {
            if value < range.start {
                return false;
            } else if range.start <= value && value < range.end() {
                return true;
            }
        }
        return false;
    }

    pub fn contained_length_from_value(&self, value: usize) -> usize {
        for range in self.ranges.iter() {
            if value < range.start {
                return 0;
            } else if range.start <= value && value < range.end() {
                return range.end() - value;
            }
        }
        return 0;
    }

    #[allow(dead_code)]
    pub fn contains_range_set(&self, other: &RangeSet) -> bool {
        for range in other.ranges.iter() {
            if self.contained_length_from_value(range.start) < range.length {
                return false;
            }
        }
        true
    }

    pub fn add_range(&mut self, range: &Range) {
        if range.length == 0 {
            // the interval is empty -> nothing to do.
            return;
        }

        for index in 0..self.ranges.len() {
            // the new range is clear of any ranges we already iterated over.
            if range.end() < self.ranges[index].start {
                // the new range starts after anything we already passed and ends before the next range starts (they don't touch) -> insert it.
                self.ranges.insert(index, *range);
                return;
            } else if range.start <= self.ranges[index].end()
                && self.ranges[index].start <= range.end()
            {
                // the new range overlaps (or touches) the first range. They are to be merged.
                // In addition we might have to merge further ranges in as well.

                let mut new_range = *range;

                while index < self.ranges.len() && self.ranges[index].start <= new_range.end() {
                    let new_end = max(new_range.end(), self.ranges[index].end());
                    new_range.start = min(new_range.start, self.ranges[index].start);
                    new_range.length = new_end - new_range.start;
                    self.ranges.remove(index);
                }

                self.ranges.insert(index, new_range);
                return;
            }
        }

        // the new range is after everything else -> just add it
        self.ranges.push(*range);
    }

    #[allow(dead_code)]
    pub fn add_range_set(&mut self, other: &RangeSet) {
        for range in other.ranges.iter() {
            self.add_range(range);
        }
    }

    #[allow(dead_code)]
    pub fn union(&self, other: &RangeSet) -> RangeSet {
        let mut result = self.clone();
        result.add_range_set(other);
        return result;
    }

    pub fn subtract_range(&mut self, range: &Range) {
        if range.length == 0 {
            return;
        }

        for index in 0..self.ranges.len() {
            // the ranges we already passed don't overlap with the range to remove

            if range.end() <= self.ranges[index].start {
                // the remaining ranges are past the one to subtract. -> we're done.
                return;
            } else if range.start <= self.ranges[index].start
                && self.ranges[index].start < range.end()
            {
                // the range to subtract started before the current range and reaches into the current range
                // -> we have to remove the beginning of the range or the entire range and do the same for following ranges.

                while index < self.ranges.len() && self.ranges[index].end() <= range.end() {
                    self.ranges.remove(index);
                }

                if index < self.ranges.len() && self.ranges[index].start < range.end() {
                    self.ranges[index].length -= range.end() - self.ranges[index].start;
                    self.ranges[index].start = range.end();
                }

                return;
            } else if range.end() < self.ranges[index].end() {
                // the range to subtract punches a hole into the current range -> we need to create two smaller ranges.

                let first_range = Range {
                    start: self.ranges[index].start,
                    length: range.start - self.ranges[index].start,
                };

                self.ranges[index].length -= range.end() - self.ranges[index].start;
                self.ranges[index].start = range.end();

                self.ranges.insert(index, first_range);

                return;
            } else if range.start < self.ranges[index].end() {
                // the range truncates the existing range -> truncate the range. Let the for loop take care of overlaps with other ranges.
                self.ranges[index].length = range.start - self.ranges[index].start;
            }
        }
    }

    pub fn subtract_range_set(&mut self, other: &RangeSet) {
        for range in other.ranges.iter() {
            self.subtract_range(range);
        }
    }

    pub fn minus(&self, other: &RangeSet) -> RangeSet {
        let mut result = self.clone();
        result.subtract_range_set(other);
        return result;
    }

    pub fn intersection(&self, other: &RangeSet) -> RangeSet {
        let mut result = RangeSet::new();

        let mut self_index: usize = 0;
        let mut other_index: usize = 0;

        while self_index < self.ranges.len() && other_index < other.ranges.len() {
            if self.ranges[self_index].end() <= other.ranges[other_index].start {
                // skip the interval
                self_index += 1;
            } else if other.ranges[other_index].end() <= self.ranges[self_index].start {
                // skip the interval
                other_index += 1;
            } else {
                // the two intervals overlap. Add the union and advance the index of the one that ends first.
                let new_start = max(
                    self.ranges[self_index].start,
                    other.ranges[other_index].start,
                );
                let new_end = min(
                    self.ranges[self_index].end(),
                    other.ranges[other_index].end(),
                );
                assert!(new_start <= new_end);
                result.add_range(&Range::new(new_start, new_end - new_start));
                if self.ranges[self_index].end() <= other.ranges[other_index].end() {
                    self_index += 1;
                } else {
                    other_index += 1;
                }
            }
        }

        return result;
    }
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#[macro_use] extern crate ruru;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate log;
extern crate toml;

#[macro_use] extern crate libimagerror;
extern crate libimagstore;
extern crate libimagrt;
#[macro_use] extern crate libimagutil;

pub mod imag;
pub mod store;
pub mod toml_utils;
pub mod ruby_utils;

#[no_mangle]
pub extern fn imag_ruby_initialize() {
    self::store::storeid::setup();
}

<commit_msg>Add setup*() calls<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#[macro_use] extern crate ruru;
#[macro_use] extern crate lazy_static;
#[macro_use] extern crate log;
extern crate toml;

#[macro_use] extern crate libimagerror;
extern crate libimagstore;
extern crate libimagrt;
#[macro_use] extern crate libimagutil;

pub mod imag;
pub mod store;
pub mod toml_utils;
pub mod ruby_utils;

#[no_mangle]
pub extern fn imag_ruby_initialize() {
    self::store::storeid::setup();
    self::store::store::entry::setup_filelockentry();
    self::store::store::entry::setup_entryheader();
    self::store::store::entry::setup_entrycontent();
    self::imag::setup();
}

<|endoftext|>


<commit_before>//! This module implements the root command of the CLI tool.

use std::env;
use std::process;

use log;
use clap::{Arg, App, AppSettings};

use prelude::*;
use constants::VERSION;
use utils::{Logger, print_error};
use config::{Config, Auth, prepare_environment};

const ABOUT: &'static str = "
Command line utility for Sentry.

This tool helps you managing remote resources on a Sentry server like
sourcemaps, debug symbols, releases or similar.  Use `--help` on the
subcommands to learn more about them.";

macro_rules! each_subcommand {
    ($mac:ident) => {
        $mac!(upload_dsym);
        $mac!(releases);
        $mac!(issues);
        $mac!(repos);
        $mac!(projects);
        $mac!(update);
        $mac!(uninstall);
        $mac!(info);
        $mac!(login);
        $mac!(send_event);
        $mac!(react_native);

        // these here exist for legacy reasons only.  They were moved
        // to subcommands of the react-native command.  Note that
        // codepush was never available on that level.
        #[cfg(target_os="macos")]
        $mac!(react_native_xcode);
        $mac!(react_native_gradle);
    }
}

// it would be great if this could be a macro expansion as well
// but rust bug #37663 breaks location information then.
pub mod upload_dsym;
pub mod releases;
pub mod issues;
pub mod repos;
pub mod projects;
pub mod update;
pub mod uninstall;
pub mod info;
pub mod login;
pub mod send_event;

pub mod react_native;
#[cfg(target_os="macos")]
pub mod react_native_xcode;
pub mod react_native_gradle;
pub mod react_native_codepush;

fn preexecute_hooks() -> Result<bool> {
    return sentry_react_native_xcode_wrap();

    #[cfg(target_os="macos")]
    fn sentry_react_native_xcode_wrap() -> Result<bool> {
        if let Ok(val) = env::var("__SENTRY_RN_WRAP_XCODE_CALL") {
            env::remove_var("__SENTRY_RN_WRAP_XCODE_CALL");
            if &val == "1" {
                react_native_xcode::wrap_call()?;
                return Ok(true);
            }
        }
        Ok(false)
    }

    #[cfg(not(target_os="macos"))]
    fn sentry_react_native_xcode_wrap() -> Result<bool> {
        Ok(false)
    }
}

/// Given an argument vector and a `Config` this executes the
/// command line and returns the result.
pub fn execute(args: Vec<String>, config: &mut Config) -> Result<()> {
    use utils::xcode;
    println!("{:?}", xcode::launched_from_xcode());

    // special case for the xcode integration for react native.  For more
    // information see commands/react_native_xcode.rs
    if preexecute_hooks()? {
        return Ok(());
    }

    let mut app = App::new("sentry-cli")
        .version(VERSION)
        .about(ABOUT)
        .max_term_width(100)
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .global_setting(AppSettings::UnifiedHelpMessage)
        .arg(Arg::with_name("url")
            .value_name("URL")
            .long("url")
            .help("The sentry API URL{n}defaults to https://sentry.io/"))
        .arg(Arg::with_name("auth_token")
            .value_name("AUTH_TOKEN")
            .long("auth-token")
            .help("The sentry auth token to use"))
        .arg(Arg::with_name("api_key")
            .value_name("API_KEY")
            .long("api-key")
            .help("The sentry API key to use"))
        .arg(Arg::with_name("log_level")
            .value_name("LOG_LEVEL")
            .long("log-level")
            .help("The log level for sentry-cli{n}\
                   (valid levels: TRACE, DEBUG, INFO, WARN, ERROR)"));

    macro_rules! add_subcommand {
        ($name:ident) => {{
            let mut cmd = $name::make_app(
                App::new(stringify!($name).replace("_", "-").as_str()));

            // for legacy reasons
            if stringify!($name).starts_with("react_native_") {
                cmd = cmd.setting(AppSettings::Hidden);
            }

            app = app.subcommand(cmd);
        }}
    }
    each_subcommand!(add_subcommand);

    let matches = app.get_matches_from_safe(args)?;

    if let Some(url) = matches.value_of("url") {
        config.url = url.to_owned();
    }
    if let Some(api_key) = matches.value_of("api_key") {
        config.auth = Some(Auth::Key(api_key.to_owned()));
    }
    if let Some(auth_token) = matches.value_of("auth_token") {
        config.auth = Some(Auth::Token(auth_token.to_owned()));
    }
    if let Some(level_str) = matches.value_of("log_level") {
        match level_str.parse() {
            Ok(level) => {
                config.log_level = level;
            }
            Err(_) => {
                fail!("Unknown log level: {}", level_str);
            }
        }
    }

    log::set_logger(|max_log_level| {
        max_log_level.set(config.log_level);
        Box::new(Logger)
    }).ok();

    config.configure_environment();

    macro_rules! execute_subcommand {
        ($name:ident) => {{
            let cmd = stringify!($name).replace("_", "-");
            if let Some(sub_matches) = matches.subcommand_matches(cmd) {
                return Ok($name::execute(&sub_matches, &config)?);
            }
        }}
    }
    each_subcommand!(execute_subcommand);
    unreachable!();
}

fn run() -> Result<()> {
    prepare_environment();
    execute(env::args().collect(), &mut Config::from_cli_config()?)
}

/// Executes the command line application and exists the process.
pub fn main() {
    match run() {
        Ok(()) => process::exit(0),
        Err(err) => {
            if let &ErrorKind::QuietExit(code) = err.kind() {
                process::exit(code);
            } else {
                print_error(&err);
                process::exit(1);
            }
        }
    }
}
<commit_msg>Removed accidental debugging code<commit_after>//! This module implements the root command of the CLI tool.

use std::env;
use std::process;

use log;
use clap::{Arg, App, AppSettings};

use prelude::*;
use constants::VERSION;
use utils::{Logger, print_error};
use config::{Config, Auth, prepare_environment};

const ABOUT: &'static str = "
Command line utility for Sentry.

This tool helps you managing remote resources on a Sentry server like
sourcemaps, debug symbols, releases or similar.  Use `--help` on the
subcommands to learn more about them.";

macro_rules! each_subcommand {
    ($mac:ident) => {
        $mac!(upload_dsym);
        $mac!(releases);
        $mac!(issues);
        $mac!(repos);
        $mac!(projects);
        $mac!(update);
        $mac!(uninstall);
        $mac!(info);
        $mac!(login);
        $mac!(send_event);
        $mac!(react_native);

        // these here exist for legacy reasons only.  They were moved
        // to subcommands of the react-native command.  Note that
        // codepush was never available on that level.
        #[cfg(target_os="macos")]
        $mac!(react_native_xcode);
        $mac!(react_native_gradle);
    }
}

// it would be great if this could be a macro expansion as well
// but rust bug #37663 breaks location information then.
pub mod upload_dsym;
pub mod releases;
pub mod issues;
pub mod repos;
pub mod projects;
pub mod update;
pub mod uninstall;
pub mod info;
pub mod login;
pub mod send_event;

pub mod react_native;
#[cfg(target_os="macos")]
pub mod react_native_xcode;
pub mod react_native_gradle;
pub mod react_native_codepush;

fn preexecute_hooks() -> Result<bool> {
    return sentry_react_native_xcode_wrap();

    #[cfg(target_os="macos")]
    fn sentry_react_native_xcode_wrap() -> Result<bool> {
        if let Ok(val) = env::var("__SENTRY_RN_WRAP_XCODE_CALL") {
            env::remove_var("__SENTRY_RN_WRAP_XCODE_CALL");
            if &val == "1" {
                react_native_xcode::wrap_call()?;
                return Ok(true);
            }
        }
        Ok(false)
    }

    #[cfg(not(target_os="macos"))]
    fn sentry_react_native_xcode_wrap() -> Result<bool> {
        Ok(false)
    }
}

/// Given an argument vector and a `Config` this executes the
/// command line and returns the result.
pub fn execute(args: Vec<String>, config: &mut Config) -> Result<()> {
    // special case for the xcode integration for react native.  For more
    // information see commands/react_native_xcode.rs
    if preexecute_hooks()? {
        return Ok(());
    }

    let mut app = App::new("sentry-cli")
        .version(VERSION)
        .about(ABOUT)
        .max_term_width(100)
        .setting(AppSettings::VersionlessSubcommands)
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .global_setting(AppSettings::UnifiedHelpMessage)
        .arg(Arg::with_name("url")
            .value_name("URL")
            .long("url")
            .help("The sentry API URL{n}defaults to https://sentry.io/"))
        .arg(Arg::with_name("auth_token")
            .value_name("AUTH_TOKEN")
            .long("auth-token")
            .help("The sentry auth token to use"))
        .arg(Arg::with_name("api_key")
            .value_name("API_KEY")
            .long("api-key")
            .help("The sentry API key to use"))
        .arg(Arg::with_name("log_level")
            .value_name("LOG_LEVEL")
            .long("log-level")
            .help("The log level for sentry-cli{n}\
                   (valid levels: TRACE, DEBUG, INFO, WARN, ERROR)"));

    macro_rules! add_subcommand {
        ($name:ident) => {{
            let mut cmd = $name::make_app(
                App::new(stringify!($name).replace("_", "-").as_str()));

            // for legacy reasons
            if stringify!($name).starts_with("react_native_") {
                cmd = cmd.setting(AppSettings::Hidden);
            }

            app = app.subcommand(cmd);
        }}
    }
    each_subcommand!(add_subcommand);

    let matches = app.get_matches_from_safe(args)?;

    if let Some(url) = matches.value_of("url") {
        config.url = url.to_owned();
    }
    if let Some(api_key) = matches.value_of("api_key") {
        config.auth = Some(Auth::Key(api_key.to_owned()));
    }
    if let Some(auth_token) = matches.value_of("auth_token") {
        config.auth = Some(Auth::Token(auth_token.to_owned()));
    }
    if let Some(level_str) = matches.value_of("log_level") {
        match level_str.parse() {
            Ok(level) => {
                config.log_level = level;
            }
            Err(_) => {
                fail!("Unknown log level: {}", level_str);
            }
        }
    }

    log::set_logger(|max_log_level| {
        max_log_level.set(config.log_level);
        Box::new(Logger)
    }).ok();

    config.configure_environment();

    macro_rules! execute_subcommand {
        ($name:ident) => {{
            let cmd = stringify!($name).replace("_", "-");
            if let Some(sub_matches) = matches.subcommand_matches(cmd) {
                return Ok($name::execute(&sub_matches, &config)?);
            }
        }}
    }
    each_subcommand!(execute_subcommand);
    unreachable!();
}

fn run() -> Result<()> {
    prepare_environment();
    execute(env::args().collect(), &mut Config::from_cli_config()?)
}

/// Executes the command line application and exists the process.
pub fn main() {
    match run() {
        Ok(()) => process::exit(0),
        Err(err) => {
            if let &ErrorKind::QuietExit(code) = err.kind() {
                process::exit(code);
            } else {
                print_error(&err);
                process::exit(1);
            }
        }
    }
}
<|endoftext|>