<commit_before>use crate::internal::prelude::*;
use serde::de::{
    self,
    Deserialize,
    Deserializer,
    MapAccess,
    Visitor
};
use serde::ser::Serializer;
use super::super::prelude::*;
use std::{
    collections::HashMap,
    mem::transmute,
    fmt,
};

/// Determines to what entity an action was used on.
#[derive(Debug)]
#[repr(u8)]
pub enum Target {
    Guild = 10,
    Channel = 20,
    User = 30,
    Role = 40,
    Invite = 50,
    Webhook = 60,
    Emoji = 70,
    #[doc(hidden)]
    __Nonexhaustive,
}

/// Determines the action that was done on a target.
#[derive(Debug)]
pub enum Action {
    GuildUpdate,
    Channel(ActionChannel),
    ChannelOverwrite(ActionChannelOverwrite),
    Member(ActionMember),
    Role(ActionRole),
    Invite(ActionInvite),
    Webhook(ActionWebhook),
    Emoji(ActionEmoji),
    MessageDelete,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl Action {
    pub fn num(&self) -> u8 {
        use self::Action::*;

        match *self {
            GuildUpdate => 1,
            Action::Channel(ref x) => x.num(),
            Action::ChannelOverwrite(ref x) => x.num(),
            Action::Member(ref x) => x.num(),
            Action::Role(ref x) => x.num(),
            Action::Invite(ref x) => x.num(),
            Action::Webhook(ref x) => x.num(),
            Action::Emoji(ref x) => x.num(),
            Action::MessageDelete => 72,
            Action::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionChannel {
    Create = 10,
    Update = 11,
    Delete = 12,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionChannel {
    pub fn num(&self) -> u8 {
        match *self {
            ActionChannel::Create => 10,
            ActionChannel::Update => 11,
            ActionChannel::Delete => 12,
            ActionChannel::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionChannelOverwrite {
    Create = 13,
    Update = 14,
    Delete = 15,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionChannelOverwrite {
    pub fn num(&self) -> u8 {
        match *self {
            ActionChannelOverwrite::Create => 13,
            ActionChannelOverwrite::Update => 14,
            ActionChannelOverwrite::Delete => 15,
            ActionChannelOverwrite::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionMember {
    Kick = 20,
    Prune = 21,
    BanAdd = 22,
    BanRemove = 23,
    Update = 24,
    RoleUpdate = 25,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionMember {
    pub fn num(&self) -> u8 {
        match *self {
            ActionMember::Kick => 20,
            ActionMember::Prune => 21,
            ActionMember::BanAdd => 22,
            ActionMember::BanRemove => 23,
            ActionMember::Update => 24,
            ActionMember::RoleUpdate => 25,
            ActionMember::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionRole {
    Create = 30,
    Update = 31,
    Delete = 32,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionRole {
    pub fn num(&self) -> u8 {
        match *self {
            ActionRole::Create => 30,
            ActionRole::Update => 31,
            ActionRole::Delete => 32,
            ActionRole::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionInvite {
    Create = 40,
    Update = 41,
    Delete = 42,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionInvite {
    pub fn num(&self) -> u8 {
        match *self {
            ActionInvite::Create => 40,
            ActionInvite::Update => 41,
            ActionInvite::Delete => 42,
            ActionInvite::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionWebhook {
    Create = 50,
    Update = 51,
    Delete = 52,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionWebhook {
    pub fn num(&self) -> u8 {
        match *self {
            ActionWebhook::Create => 50,
            ActionWebhook::Update => 51,
            ActionWebhook::Delete => 52,
            ActionWebhook::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionEmoji {
    Create = 60,
    Delete = 61,
    Update = 62,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionEmoji {
    pub fn num(&self) -> u8 {
        match *self {
            ActionEmoji::Create => 60,
            ActionEmoji::Update => 61,
            ActionEmoji::Delete => 62,
            ActionEmoji::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Change {
    #[serde(rename = "key")] pub name: String,
    // TODO: Change these to an actual type.
    #[serde(rename = "old_value")] pub old: Option<Value>,
    #[serde(rename = "new_value")] pub new: Option<Value>,
}

#[derive(Debug)]
pub struct AuditLogs {
    pub entries: HashMap<AuditLogEntryId, AuditLogEntry>,
    pub webhooks: Vec<Webhook>,
    pub users: Vec<User>,
    pub(crate) _nonexhaustive: (),
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AuditLogEntry {
    /// Determines to what entity an [`action`] was used on.
    ///
    /// [`action`]: #structfield.action
    #[serde(with = "option_u64_handler")]
    pub target_id: Option<u64>,
    /// Determines what action was done on a [`target`]
    ///
    /// [`target`]: #structfield.target
    #[serde(
        with = "action_handler",
        rename = "action_type"
    )]
    pub action: Action,
    /// What was the reasoning by doing an action on a target? If there was one.
    pub reason: Option<String>,
    /// The user that did this action on a target.
    pub user_id: UserId,
    /// What changes were made.
    pub changes: Option<Vec<Change>>,
    /// The id of this entry.
    pub id: AuditLogEntryId,
    /// Some optional data assosiated with this entry.
    pub options: Option<Options>,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Options {
    /// Number of days after which inactive members were kicked.
    #[serde(default, with = "option_u64_handler")]
    pub delete_member_days: Option<u64>,
    /// Number of members removed by the prune
    #[serde(default, with = "option_u64_handler")]
    pub members_removed: Option<u64>,
    /// Channel in which the messages were deleted
    #[serde(default)]
    pub channel_id: Option<ChannelId>,
    /// Number of deleted messages.
    #[serde(default, with = "option_u64_handler")]
    pub count: Option<u64>,
    /// Id of the overwritten entity
    #[serde(default, with = "option_u64_handler")]
    pub id: Option<u64>,
    /// Type of overwritten entity ("member" or "role").
    #[serde(default, rename = "type")]
    pub kind: Option<String>,
    /// Name of the role if type is "role"
    #[serde(default)]
    pub role_name: Option<String>,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}

mod option_u64_handler {
    use super::*;

    pub fn deserialize<'de, D: Deserializer<'de>>(des: D) -> StdResult<Option<u64>, D::Error> {
        struct OptionU64Visitor;

        impl<'de> Visitor<'de> for OptionU64Visitor {
            type Value = Option<u64>;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("an optional integer or a string with a valid number inside")
            }

            fn visit_some<D: Deserializer<'de>>(self, deserializer: D) -> StdResult<Self::Value, D::Error> {
                deserializer.deserialize_any(OptionU64Visitor)
            }

            fn visit_none<E: de::Error>(self) -> StdResult<Self::Value, E> {
                Ok(None)
            }

            fn visit_u64<E: de::Error>(self, val: u64) -> StdResult<Option<u64>, E> {
                Ok(Some(val))
            }

            fn visit_str<E: de::Error>(self, string: &str) -> StdResult<Option<u64>, E> {
                string.parse().map(Some).map_err(de::Error::custom)
            }
        }

        des.deserialize_option(OptionU64Visitor)
    }

    pub fn serialize<S: Serializer>(num: &Option<u64>, s: S) -> StdResult<S::Ok, S::Error> {
        use serde::Serialize;

        Option::serialize(num, s)
    }
}

mod action_handler {
    use super::*;

    pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> StdResult<Action, D::Error> {
        struct ActionVisitor;

        impl<'de> Visitor<'de> for ActionVisitor {
            type Value = Action;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("an integer between 1 to 72")
            }

            // NOTE: Serde internally delegates number types below `u64` to it.
            fn visit_u64<E: de::Error>(self, value: u64) -> StdResult<Action, E> {
                let value = value as u8;

                Ok(match value {
                    1 => Action::GuildUpdate,
                    10..=12 => Action::Channel(unsafe { transmute(value) }),
                    13..=15 => Action::ChannelOverwrite(unsafe { transmute(value) }),
                    20..=25 => Action::Member(unsafe { transmute(value) }),
                    30..=32 => Action::Role(unsafe { transmute(value) }),
                    40..=42 => Action::Invite(unsafe { transmute(value) }),
                    50..=52 => Action::Webhook(unsafe { transmute(value) }),
                    60..=62 => Action::Emoji(unsafe { transmute(value) }),
                    72 => Action::MessageDelete,
                    _ => return Err(E::custom(format!("Unexpected action number: {}", value))),
                })
            }
        }

        de.deserialize_any(ActionVisitor)
    }

    pub fn serialize<S: Serializer>(
        action: &Action,
        serializer: S,
    ) -> StdResult<S::Ok, S::Error> {
        serializer.serialize_u8(action.num())
    }
}
impl<'de> Deserialize<'de> for AuditLogs {
    fn deserialize<D: Deserializer<'de>>(de: D) -> StdResult<Self, D::Error> {
        #[derive(Deserialize)]
        #[serde(field_identifier)]
        enum Field {
            #[serde(rename = "audit_log_entries")] Entries,
            #[serde(rename = "webhooks")] Webhooks,
            #[serde(rename = "users")] Users,
            // TODO(field added by Discord, undocumented) #[serde(rename = "integrations")] Integrations,
        }

        struct EntriesVisitor;

        impl<'de> Visitor<'de> for EntriesVisitor {
            type Value = AuditLogs;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("audit log entries")
            }

            fn visit_map<V: MapAccess<'de>>(self, mut map: V) -> StdResult<AuditLogs, V::Error> {
                let mut audit_log_entries = None;
                let mut users = None;
                let mut webhooks = None;

                loop {
                    match map.next_key() {
                        Ok(Some(Field::Entries)) => {
                            if audit_log_entries.is_some() {
                                return Err(de::Error::duplicate_field("entries"));
                            }

                            audit_log_entries = Some(map.next_value::<Vec<AuditLogEntry>>()?);
                        }
                        Ok(Some(Field::Webhooks)) => {
                            if webhooks.is_some() {
                                return Err(de::Error::duplicate_field("webhooks"));
                            }

                            webhooks = Some(map.next_value::<Vec<Webhook>>()?);
                        }
                        Ok(Some(Field::Users)) => {
                            if users.is_some() {
                                return Err(de::Error::duplicate_field("users"));
                            }

                            users = Some(map.next_value::<Vec<User>>()?);
                        }
                        Ok(None) => break, // No more keys
                        Err(e) => if e.to_string().contains("unknown field") {
                            // e is of type <V as MapAccess>::Error, which is a macro-defined trait, ultimately
                            // implemented by serde::de::value::Error. Seeing as every error is a simple string and not
                            // using a proper Error num, the best we can do here is to check if the string contains
                            // this error. This was added because Discord randomly started sending new fields.
                            // But no JSON deserializer should ever error over this.
                            map.next_value::<serde_json::Value>()?; // Actually read the value to avoid syntax errors
                        } else {
                            return Err(e)
                        }
                    }
                }

                Ok(AuditLogs {
                    entries: audit_log_entries
                        .unwrap()
                        .into_iter()
                        .map(|entry| (entry.id, entry))
                        .collect(),
                    webhooks: webhooks.unwrap(),
                    users: users.unwrap(),
                    _nonexhaustive: (),
                })
            }
        }

        const FIELD: &[&str] = &["audit_log_entries"];
        de.deserialize_struct("AuditLogs", FIELD, EntriesVisitor)
    }
}
<commit_msg>Add new auditlog type enums (#744)<commit_after>use crate::internal::prelude::*;
use serde::de::{
    self,
    Deserialize,
    Deserializer,
    MapAccess,
    Visitor
};
use serde::ser::Serializer;
use super::super::prelude::*;
use std::{
    collections::HashMap,
    mem::transmute,
    fmt,
};

/// Determines to what entity an action was used on.
#[derive(Debug)]
#[repr(u8)]
pub enum Target {
    Guild = 10,
    Channel = 20,
    User = 30,
    Role = 40,
    Invite = 50,
    Webhook = 60,
    Emoji = 70,
    Integration = 80,
    #[doc(hidden)]
    __Nonexhaustive,
}

/// Determines the action that was done on a target.
#[derive(Debug)]
pub enum Action {
    GuildUpdate,
    Channel(ActionChannel),
    ChannelOverwrite(ActionChannelOverwrite),
    Member(ActionMember),
    Role(ActionRole),
    Invite(ActionInvite),
    Webhook(ActionWebhook),
    Emoji(ActionEmoji),
    Message(ActionMessage),
    Integration(ActionIntegration),
    #[doc(hidden)]
    __Nonexhaustive,
}

impl Action {
    pub fn num(&self) -> u8 {
        use self::Action::*;

        match *self {
            GuildUpdate => 1,
            Action::Channel(ref x) => x.num(),
            Action::ChannelOverwrite(ref x) => x.num(),
            Action::Member(ref x) => x.num(),
            Action::Role(ref x) => x.num(),
            Action::Invite(ref x) => x.num(),
            Action::Webhook(ref x) => x.num(),
            Action::Emoji(ref x) => x.num(),
            Action::Message(ref x) => x.num(),
            Action::Integration(ref x) => x.num(),
            Action::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionChannel {
    Create = 10,
    Update = 11,
    Delete = 12,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionChannel {
    pub fn num(&self) -> u8 {
        match *self {
            ActionChannel::Create => 10,
            ActionChannel::Update => 11,
            ActionChannel::Delete => 12,
            ActionChannel::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionChannelOverwrite {
    Create = 13,
    Update = 14,
    Delete = 15,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionChannelOverwrite {
    pub fn num(&self) -> u8 {
        match *self {
            ActionChannelOverwrite::Create => 13,
            ActionChannelOverwrite::Update => 14,
            ActionChannelOverwrite::Delete => 15,
            ActionChannelOverwrite::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionMember {
    Kick = 20,
    Prune = 21,
    BanAdd = 22,
    BanRemove = 23,
    Update = 24,
    RoleUpdate = 25,
    MemberMove = 26,
    MemberDisconnect = 27,
    BotAdd = 28,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionMember {
    pub fn num(&self) -> u8 {
        match *self {
            ActionMember::Kick => 20,
            ActionMember::Prune => 21,
            ActionMember::BanAdd => 22,
            ActionMember::BanRemove => 23,
            ActionMember::Update => 24,
            ActionMember::RoleUpdate => 25,
            ActionMember::MemberMove => 26,
            ActionMember::MemberDisconnect => 27,
            ActionMember::BotAdd => 28,
            ActionMember::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionRole {
    Create = 30,
    Update = 31,
    Delete = 32,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionRole {
    pub fn num(&self) -> u8 {
        match *self {
            ActionRole::Create => 30,
            ActionRole::Update => 31,
            ActionRole::Delete => 32,
            ActionRole::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionInvite {
    Create = 40,
    Update = 41,
    Delete = 42,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionInvite {
    pub fn num(&self) -> u8 {
        match *self {
            ActionInvite::Create => 40,
            ActionInvite::Update => 41,
            ActionInvite::Delete => 42,
            ActionInvite::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionWebhook {
    Create = 50,
    Update = 51,
    Delete = 52,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionWebhook {
    pub fn num(&self) -> u8 {
        match *self {
            ActionWebhook::Create => 50,
            ActionWebhook::Update => 51,
            ActionWebhook::Delete => 52,
            ActionWebhook::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionEmoji {
    Create = 60,
    Delete = 61,
    Update = 62,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionEmoji {
    pub fn num(&self) -> u8 {
        match *self {
            ActionEmoji::Create => 60,
            ActionEmoji::Update => 61,
            ActionEmoji::Delete => 62,
            ActionEmoji::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionMessage {
    Delete = 72,
    BulkDelete = 73,
    Pin = 74,
    Unpin = 75,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionMessage {
    pub fn num(&self) -> u8 {
        match *self {
            ActionMessage::Delete => 72,
            ActionMessage::BulkDelete => 73,
            ActionMessage::Pin => 74,
            ActionMessage::Unpin => 75,
            ActionMessage::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionIntegration {
    Create = 80,
    Update = 81,
    Delete = 82,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionIntegration {
    pub fn num(&self) -> u8 {
        match *self {
            ActionIntegration::Create => 80,
            ActionIntegration::Update => 81,
            ActionIntegration::Delete => 82,
            ActionIntegration::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Change {
    #[serde(rename = "key")] pub name: String,
    // TODO: Change these to an actual type.
    #[serde(rename = "old_value")] pub old: Option<Value>,
    #[serde(rename = "new_value")] pub new: Option<Value>,
}

#[derive(Debug)]
pub struct AuditLogs {
    pub entries: HashMap<AuditLogEntryId, AuditLogEntry>,
    pub webhooks: Vec<Webhook>,
    pub users: Vec<User>,
    pub(crate) _nonexhaustive: (),
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AuditLogEntry {
    /// Determines to what entity an [`action`] was used on.
    ///
    /// [`action`]: #structfield.action
    #[serde(with = "option_u64_handler")]
    pub target_id: Option<u64>,
    /// Determines what action was done on a [`target`]
    ///
    /// [`target`]: #structfield.target
    #[serde(
        with = "action_handler",
        rename = "action_type"
    )]
    pub action: Action,
    /// What was the reasoning by doing an action on a target? If there was one.
    pub reason: Option<String>,
    /// The user that did this action on a target.
    pub user_id: UserId,
    /// What changes were made.
    pub changes: Option<Vec<Change>>,
    /// The id of this entry.
    pub id: AuditLogEntryId,
    /// Some optional data assosiated with this entry.
    pub options: Option<Options>,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Options {
    /// Number of days after which inactive members were kicked.
    #[serde(default, with = "option_u64_handler")]
    pub delete_member_days: Option<u64>,
    /// Number of members removed by the prune
    #[serde(default, with = "option_u64_handler")]
    pub members_removed: Option<u64>,
    /// Channel in which the messages were deleted
    #[serde(default)]
    pub channel_id: Option<ChannelId>,
    /// Number of deleted messages.
    #[serde(default, with = "option_u64_handler")]
    pub count: Option<u64>,
    /// Id of the overwritten entity
    #[serde(default, with = "option_u64_handler")]
    pub id: Option<u64>,
    /// Type of overwritten entity ("member" or "role").
    #[serde(default, rename = "type")]
    pub kind: Option<String>,
    /// Name of the role if type is "role"
    #[serde(default)]
    pub role_name: Option<String>,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}

mod option_u64_handler {
    use super::*;

    pub fn deserialize<'de, D: Deserializer<'de>>(des: D) -> StdResult<Option<u64>, D::Error> {
        struct OptionU64Visitor;

        impl<'de> Visitor<'de> for OptionU64Visitor {
            type Value = Option<u64>;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("an optional integer or a string with a valid number inside")
            }

            fn visit_some<D: Deserializer<'de>>(self, deserializer: D) -> StdResult<Self::Value, D::Error> {
                deserializer.deserialize_any(OptionU64Visitor)
            }

            fn visit_none<E: de::Error>(self) -> StdResult<Self::Value, E> {
                Ok(None)
            }

            fn visit_u64<E: de::Error>(self, val: u64) -> StdResult<Option<u64>, E> {
                Ok(Some(val))
            }

            fn visit_str<E: de::Error>(self, string: &str) -> StdResult<Option<u64>, E> {
                string.parse().map(Some).map_err(de::Error::custom)
            }
        }

        des.deserialize_option(OptionU64Visitor)
    }

    pub fn serialize<S: Serializer>(num: &Option<u64>, s: S) -> StdResult<S::Ok, S::Error> {
        use serde::Serialize;

        Option::serialize(num, s)
    }
}

mod action_handler {
    use super::*;

    pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> StdResult<Action, D::Error> {
        struct ActionVisitor;

        impl<'de> Visitor<'de> for ActionVisitor {
            type Value = Action;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("an integer between 1 to 72")
            }

            // NOTE: Serde internally delegates number types below `u64` to it.
            fn visit_u64<E: de::Error>(self, value: u64) -> StdResult<Action, E> {
                let value = value as u8;

                Ok(match value {
                    1 => Action::GuildUpdate,
                    10..=12 => Action::Channel(unsafe { transmute(value) }),
                    13..=15 => Action::ChannelOverwrite(unsafe { transmute(value) }),
                    20..=28 => Action::Member(unsafe { transmute(value) }),
                    30..=32 => Action::Role(unsafe { transmute(value) }),
                    40..=42 => Action::Invite(unsafe { transmute(value) }),
                    50..=52 => Action::Webhook(unsafe { transmute(value) }),
                    60..=62 => Action::Emoji(unsafe { transmute(value) }),
                    72..=75 => Action::Message(unsafe { transmute(value) }),
                    80..=82 => Action::Integration(unsafe { transmute(value) }),
                    _ => return Err(E::custom(format!("Unexpected action number: {}", value))),
                })
            }
        }

        de.deserialize_any(ActionVisitor)
    }

    pub fn serialize<S: Serializer>(
        action: &Action,
        serializer: S,
    ) -> StdResult<S::Ok, S::Error> {
        serializer.serialize_u8(action.num())
    }
}
impl<'de> Deserialize<'de> for AuditLogs {
    fn deserialize<D: Deserializer<'de>>(de: D) -> StdResult<Self, D::Error> {
        #[derive(Deserialize)]
        #[serde(field_identifier)]
        enum Field {
            #[serde(rename = "audit_log_entries")] Entries,
            #[serde(rename = "webhooks")] Webhooks,
            #[serde(rename = "users")] Users,
            // TODO(field added by Discord, undocumented) #[serde(rename = "integrations")] Integrations,
        }

        struct EntriesVisitor;

        impl<'de> Visitor<'de> for EntriesVisitor {
            type Value = AuditLogs;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("audit log entries")
            }

            fn visit_map<V: MapAccess<'de>>(self, mut map: V) -> StdResult<AuditLogs, V::Error> {
                let mut audit_log_entries = None;
                let mut users = None;
                let mut webhooks = None;

                loop {
                    match map.next_key() {
                        Ok(Some(Field::Entries)) => {
                            if audit_log_entries.is_some() {
                                return Err(de::Error::duplicate_field("entries"));
                            }

                            audit_log_entries = Some(map.next_value::<Vec<AuditLogEntry>>()?);
                        }
                        Ok(Some(Field::Webhooks)) => {
                            if webhooks.is_some() {
                                return Err(de::Error::duplicate_field("webhooks"));
                            }

                            webhooks = Some(map.next_value::<Vec<Webhook>>()?);
                        }
                        Ok(Some(Field::Users)) => {
                            if users.is_some() {
                                return Err(de::Error::duplicate_field("users"));
                            }

                            users = Some(map.next_value::<Vec<User>>()?);
                        }
                        Ok(None) => break, // No more keys
                        Err(e) => if e.to_string().contains("unknown field") {
                            // e is of type <V as MapAccess>::Error, which is a macro-defined trait, ultimately
                            // implemented by serde::de::value::Error. Seeing as every error is a simple string and not
                            // using a proper Error num, the best we can do here is to check if the string contains
                            // this error. This was added because Discord randomly started sending new fields.
                            // But no JSON deserializer should ever error over this.
                            map.next_value::<serde_json::Value>()?; // Actually read the value to avoid syntax errors
                        } else {
                            return Err(e)
                        }
                    }
                }

                Ok(AuditLogs {
                    entries: audit_log_entries
                        .unwrap()
                        .into_iter()
                        .map(|entry| (entry.id, entry))
                        .collect(),
                    webhooks: webhooks.unwrap(),
                    users: users.unwrap(),
                    _nonexhaustive: (),
                })
            }
        }

        const FIELD: &[&str] = &["audit_log_entries"];
        de.deserialize_struct("AuditLogs", FIELD, EntriesVisitor)
    }
}
<|endoftext|>


<commit_before>use std::any::*;

use backend::Backend;
use expression::{Expression, NonAggregate, SelectableExpression};
use expression::operators::Eq;
use insertable::*;
#[cfg(feature = "mysql")]
use mysql::Mysql;
use query_builder::*;
#[cfg(feature = "sqlite")]
use query_dsl::ExecuteDsl;
use query_source::{Column, Table};
use result::QueryResult;
#[cfg(feature = "sqlite")]
use sqlite::{Sqlite, SqliteConnection};
use super::returning_clause::*;

/// The structure returned by [`insert_into`](../../fn.insert_into.html).
#[derive(Debug, Clone, Copy)]
pub struct IncompleteInsertStatement<T, Op> {
    target: T,
    operator: Op,
}

impl<T, Op> IncompleteInsertStatement<T, Op> {
    pub(crate) fn new(target: T, operator: Op) -> Self {
        IncompleteInsertStatement { target, operator }
    }

    /// Inserts `DEFAULT VALUES` into the targeted table.
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("../doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users (name) {
    /// #         name -> Text,
    /// #         hair_color -> Text,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use diesel::insert_into;
    /// #     use users::dsl::*;
    /// #     let connection = connection_no_data();
    /// connection.execute("CREATE TABLE users (
    ///     name VARCHAR(255) NOT NULL DEFAULT 'Sean',
    ///     hair_color VARCHAR(255) NOT NULL DEFAULT 'Green'
    /// )").unwrap();
    ///
    /// insert_into(users)
    ///     .default_values()
    ///     .execute(&connection)
    ///     .unwrap();
    ///
    /// let expected_data = vec![
    ///     ("Sean".to_string(), "Green".to_string()),
    /// ];
    /// assert_eq!(Ok(expected_data), users.load(&connection));
    /// # }
    /// ```
    pub fn default_values(self) -> InsertStatement<T, DefaultValues, Op> {
        static STATIC_DEFAULT_VALUES: &'static DefaultValues = &DefaultValues;
        self.values(STATIC_DEFAULT_VALUES)
    }

    /// Inserts the given values into the table passed to `insert_into`.
    ///
    /// See the documentation of [`insert_into`](../fn.insert_into.html) for
    /// usage examples.
    pub fn values<U>(self, records: U) -> InsertStatement<T, U::Values, Op>
    where
        U: Insertable<T>,
    {
        InsertStatement::new(
            self.target,
            records.values(),
            self.operator,
            NoReturningClause,
        )
    }
}

/// The structure returned by [`insert`](/diesel/fn.insert.html). The only thing that can be done with it
/// is call `into`.
#[derive(Debug, Copy, Clone)]
#[cfg(feature = "with-deprecated")]
pub struct DeprecatedIncompleteInsertStatement<T, Op> {
    records: T,
    operator: Op,
}

#[cfg(feature = "with-deprecated")]
impl<T, Op> DeprecatedIncompleteInsertStatement<T, Op> {
    #[doc(hidden)]
    pub fn new(records: T, operator: Op) -> Self {
        DeprecatedIncompleteInsertStatement {
            records: records,
            operator: operator,
        }
    }

    /// Specify which table the data passed to `insert` should be added to.
    pub fn into<S>(self, target: S) -> InsertStatement<S, T::Values, Op>
    where
        T: Insertable<S>,
    {
        InsertStatement::new(
            target,
            self.records.values(),
            self.operator,
            NoReturningClause,
        )
    }
}

#[derive(Debug, Copy, Clone)]
pub struct InsertStatement<T, U, Op = Insert, Ret = NoReturningClause> {
    operator: Op,
    target: T,
    records: U,
    returning: Ret,
}

impl<T, U, Op, Ret> InsertStatement<T, U, Op, Ret> {
    fn new(target: T, records: U, operator: Op, returning: Ret) -> Self {
        InsertStatement {
            operator: operator,
            target: target,
            records: records,
            returning: returning,
        }
    }

    #[cfg(feature = "postgres")]
    pub(crate) fn replace_values<F, V>(self, f: F) -> InsertStatement<T, V, Op, Ret>
    where
        F: FnOnce(U) -> V,
    {
        InsertStatement::new(self.target, f(self.records), self.operator, self.returning)
    }
}

impl<T, U, Op, Ret, DB> QueryFragment<DB> for InsertStatement<T, U, Op, Ret>
where
    DB: Backend,
    T: Table,
    T::FromClause: QueryFragment<DB>,
    U: InsertValues<T, DB> + CanInsertInSingleQuery<DB>,
    Op: QueryFragment<DB>,
    Ret: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.unsafe_to_cache_prepared();

        if self.records.rows_to_insert() == 0 {
            out.push_sql("SELECT 1 FROM ");
            self.target.from_clause().walk_ast(out.reborrow())?;
            out.push_sql(" WHERE 1=0");
            return Ok(());
        }

        self.operator.walk_ast(out.reborrow())?;
        out.push_sql(" INTO ");
        self.target.from_clause().walk_ast(out.reborrow())?;
        if self.records.is_noop() {
            out.push_sql(" DEFAULT VALUES");
        } else {
            out.push_sql(" (");
            if let Some(builder) = out.reborrow().query_builder() {
                self.records.column_names(builder)?;
            }
            out.push_sql(") VALUES ");
            if self.records.requires_parenthesis() {
                out.push_sql("(");
            }
            self.records.walk_ast(out.reborrow())?;
            if self.records.requires_parenthesis() {
                out.push_sql(")");
            }
        }
        self.returning.walk_ast(out.reborrow())?;
        Ok(())
    }
}

#[cfg(feature = "sqlite")]
impl<'a, T, U, Op> ExecuteDsl<SqliteConnection> for InsertStatement<T, &'a [U], Op>
where
    &'a U: Insertable<T>,
    InsertStatement<T, <&'a U as Insertable<T>>::Values, Op>: QueryFragment<Sqlite>,
    T: Copy,
    Op: Copy,
{
    fn execute(self, conn: &SqliteConnection) -> QueryResult<usize> {
        use connection::Connection;
        conn.transaction(|| {
            let mut result = 0;
            for record in self.records {
                result += InsertStatement::new(
                    self.target,
                    record.values(),
                    self.operator,
                    self.returning,
                ).execute(conn)?;
            }
            Ok(result)
        })
    }
}

impl_query_id!(noop: InsertStatement<T, U, Op, Ret>);

impl<T, U, Op> AsQuery for InsertStatement<T, U, Op, NoReturningClause>
where
    T: Table,
    InsertStatement<T, U, Op, ReturningClause<T::AllColumns>>: Query,
{
    type SqlType = <Self::Query as Query>::SqlType;
    type Query = InsertStatement<T, U, Op, ReturningClause<T::AllColumns>>;

    fn as_query(self) -> Self::Query {
        self.returning(T::all_columns())
    }
}

impl<T, U, Op, Ret> Query for InsertStatement<T, U, Op, ReturningClause<Ret>>
where
    Ret: Expression + SelectableExpression<T> + NonAggregate,
{
    type SqlType = Ret::SqlType;
}

impl<T, U, Op> InsertStatement<T, U, Op> {
    /// Specify what expression is returned after execution of the `insert`.
    /// # Examples
    ///
    /// ### Inserting records:
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("../doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # #[cfg(feature = "postgres")]
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let new_users = vec![
    ///     NewUser { name: "Timmy".to_string(), },
    ///     NewUser { name: "Jimmy".to_string(), },
    /// ];
    ///
    /// let inserted_names = diesel::insert_into(users)
    ///     .values(&new_users)
    ///     .returning(name)
    ///     .get_results(&connection);
    /// assert_eq!(Ok(vec!["Timmy".to_string(), "Jimmy".to_string()]), inserted_names);
    /// # }
    /// # #[cfg(not(feature = "postgres"))]
    /// # fn main() {}
    /// ```
    pub fn returning<E>(self, returns: E) -> InsertStatement<T, U, Op, ReturningClause<E>>
    where
        InsertStatement<T, U, Op, ReturningClause<E>>: Query,
    {
        InsertStatement::new(
            self.target,
            self.records,
            self.operator,
            ReturningClause(returns),
        )
    }
}

#[derive(Debug, Copy, Clone)]
#[doc(hidden)]
pub struct Insert;

impl<DB: Backend> QueryFragment<DB> for Insert {
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("INSERT");
        Ok(())
    }
}

impl_query_id!(Insert);

#[derive(Debug, Copy, Clone)]
#[doc(hidden)]
pub struct Replace;

#[cfg(feature = "sqlite")]
impl QueryFragment<Sqlite> for Replace {
    fn walk_ast(&self, mut out: AstPass<Sqlite>) -> QueryResult<()> {
        out.push_sql("REPLACE");
        Ok(())
    }
}

#[cfg(feature = "mysql")]
impl QueryFragment<Mysql> for Replace {
    fn walk_ast(&self, mut out: AstPass<Mysql>) -> QueryResult<()> {
        out.push_sql("REPLACE");
        Ok(())
    }
}

impl_query_id!(Replace);

/// Marker trait to indicate that no additional operations have been added
/// to a record for insert. Used to prevent things like
/// `insert(&vec![user.on_conflict_do_nothing(), user2.on_conflict_do_nothing()])`
/// from compiling.
pub trait UndecoratedInsertRecord<Table> {}

impl<'a, T, Tab> UndecoratedInsertRecord<Tab> for &'a T
where
    T: ?Sized + UndecoratedInsertRecord<Tab>,
{
}

impl<T, U> UndecoratedInsertRecord<T::Table> for ColumnInsertValue<T, U>
where
    T: Column,
{
}

impl<T, Table> UndecoratedInsertRecord<Table> for [T]
where
    T: UndecoratedInsertRecord<Table>,
{
}

impl<T, Table> UndecoratedInsertRecord<Table> for Vec<T>
where
    [T]: UndecoratedInsertRecord<Table>,
{
}

impl<Lhs, Rhs> UndecoratedInsertRecord<Lhs::Table> for Eq<Lhs, Rhs>
where
    Lhs: Column,
{
}

impl<Lhs, Rhs, Tab> UndecoratedInsertRecord<Tab> for Option<Eq<Lhs, Rhs>>
where
    Eq<Lhs, Rhs>: UndecoratedInsertRecord<Tab>,
{
}

#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct DefaultValues;

impl<DB: Backend> CanInsertInSingleQuery<DB> for DefaultValues {
    fn rows_to_insert(&self) -> usize {
        1
    }
}

impl<'a, Tab> Insertable<Tab> for &'a DefaultValues {
    type Values = DefaultValues;

    fn values(self) -> Self::Values {
        *self
    }
}

impl<Tab, DB> InsertValues<Tab, DB> for DefaultValues
where
    Tab: Table,
    DB: Backend + Any,
{
    fn column_names(&self, _: &mut DB::QueryBuilder) -> QueryResult<()> {
        Ok(())
    }

    fn walk_ast(&self, _: AstPass<DB>) -> QueryResult<()> {
        Ok(())
    }

    #[cfg(not(feature = "mysql"))]
    fn is_noop(&self) -> bool {
        true
    }

    #[cfg(feature = "mysql")]
    fn is_noop(&self) -> bool {
        // The syntax for this on MySQL is
        // INSERT INTO table () VALUES ()
        //
        // This is hacky, but it's the easiest way to get this done without a
        // deeper restructuring of this code.
        TypeId::of::<DB>() != TypeId::of::<::mysql::Mysql>()
    }
}
<commit_msg>Document `query_builder::insert_statement`<commit_after>/// Types related to the construction of an `INSERT` statement.

use std::any::*;

use backend::Backend;
use expression::{Expression, NonAggregate, SelectableExpression};
use expression::operators::Eq;
use insertable::*;
#[cfg(feature = "mysql")]
use mysql::Mysql;
use query_builder::*;
#[cfg(feature = "sqlite")]
use query_dsl::ExecuteDsl;
use query_source::{Column, Table};
use result::QueryResult;
#[cfg(feature = "sqlite")]
use sqlite::{Sqlite, SqliteConnection};
use super::returning_clause::*;

/// The structure returned by [`insert_into`](../../fn.insert_into.html).
#[derive(Debug, Clone, Copy)]
pub struct IncompleteInsertStatement<T, Op> {
    target: T,
    operator: Op,
}

impl<T, Op> IncompleteInsertStatement<T, Op> {
    pub(crate) fn new(target: T, operator: Op) -> Self {
        IncompleteInsertStatement { target, operator }
    }

    /// Inserts `DEFAULT VALUES` into the targeted table.
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("../doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users (name) {
    /// #         name -> Text,
    /// #         hair_color -> Text,
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use diesel::insert_into;
    /// #     use users::dsl::*;
    /// #     let connection = connection_no_data();
    /// connection.execute("CREATE TABLE users (
    ///     name VARCHAR(255) NOT NULL DEFAULT 'Sean',
    ///     hair_color VARCHAR(255) NOT NULL DEFAULT 'Green'
    /// )").unwrap();
    ///
    /// insert_into(users)
    ///     .default_values()
    ///     .execute(&connection)
    ///     .unwrap();
    ///
    /// let expected_data = vec![
    ///     ("Sean".to_string(), "Green".to_string()),
    /// ];
    /// assert_eq!(Ok(expected_data), users.load(&connection));
    /// # }
    /// ```
    pub fn default_values(self) -> InsertStatement<T, DefaultValues, Op> {
        static STATIC_DEFAULT_VALUES: &'static DefaultValues = &DefaultValues;
        self.values(STATIC_DEFAULT_VALUES)
    }

    /// Inserts the given values into the table passed to `insert_into`.
    ///
    /// See the documentation of [`insert_into`](../fn.insert_into.html) for
    /// usage examples.
    pub fn values<U>(self, records: U) -> InsertStatement<T, U::Values, Op>
    where
        U: Insertable<T>,
    {
        InsertStatement::new(
            self.target,
            records.values(),
            self.operator,
            NoReturningClause,
        )
    }
}

/// The structure returned by [`insert`](/diesel/fn.insert.html). The only thing that can be done with it
/// is call `into`.
#[derive(Debug, Copy, Clone)]
#[cfg(feature = "with-deprecated")]
pub struct DeprecatedIncompleteInsertStatement<T, Op> {
    records: T,
    operator: Op,
}

#[cfg(feature = "with-deprecated")]
impl<T, Op> DeprecatedIncompleteInsertStatement<T, Op> {
    #[doc(hidden)]
    pub fn new(records: T, operator: Op) -> Self {
        DeprecatedIncompleteInsertStatement {
            records: records,
            operator: operator,
        }
    }

    /// Specify which table the data passed to `insert` should be added to.
    pub fn into<S>(self, target: S) -> InsertStatement<S, T::Values, Op>
    where
        T: Insertable<S>,
    {
        InsertStatement::new(
            target,
            self.records.values(),
            self.operator,
            NoReturningClause,
        )
    }
}

#[derive(Debug, Copy, Clone)]
pub struct InsertStatement<T, U, Op = Insert, Ret = NoReturningClause> {
    operator: Op,
    target: T,
    records: U,
    returning: Ret,
}

impl<T, U, Op, Ret> InsertStatement<T, U, Op, Ret> {
    fn new(target: T, records: U, operator: Op, returning: Ret) -> Self {
        InsertStatement {
            operator: operator,
            target: target,
            records: records,
            returning: returning,
        }
    }

    #[cfg(feature = "postgres")]
    pub(crate) fn replace_values<F, V>(self, f: F) -> InsertStatement<T, V, Op, Ret>
    where
        F: FnOnce(U) -> V,
    {
        InsertStatement::new(self.target, f(self.records), self.operator, self.returning)
    }
}

impl<T, U, Op, Ret, DB> QueryFragment<DB> for InsertStatement<T, U, Op, Ret>
where
    DB: Backend,
    T: Table,
    T::FromClause: QueryFragment<DB>,
    U: InsertValues<T, DB> + CanInsertInSingleQuery<DB>,
    Op: QueryFragment<DB>,
    Ret: QueryFragment<DB>,
{
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.unsafe_to_cache_prepared();

        if self.records.rows_to_insert() == 0 {
            out.push_sql("SELECT 1 FROM ");
            self.target.from_clause().walk_ast(out.reborrow())?;
            out.push_sql(" WHERE 1=0");
            return Ok(());
        }

        self.operator.walk_ast(out.reborrow())?;
        out.push_sql(" INTO ");
        self.target.from_clause().walk_ast(out.reborrow())?;
        if self.records.is_noop() {
            out.push_sql(" DEFAULT VALUES");
        } else {
            out.push_sql(" (");
            if let Some(builder) = out.reborrow().query_builder() {
                self.records.column_names(builder)?;
            }
            out.push_sql(") VALUES ");
            if self.records.requires_parenthesis() {
                out.push_sql("(");
            }
            self.records.walk_ast(out.reborrow())?;
            if self.records.requires_parenthesis() {
                out.push_sql(")");
            }
        }
        self.returning.walk_ast(out.reborrow())?;
        Ok(())
    }
}

#[cfg(feature = "sqlite")]
impl<'a, T, U, Op> ExecuteDsl<SqliteConnection> for InsertStatement<T, &'a [U], Op>
where
    &'a U: Insertable<T>,
    InsertStatement<T, <&'a U as Insertable<T>>::Values, Op>: QueryFragment<Sqlite>,
    T: Copy,
    Op: Copy,
{
    fn execute(self, conn: &SqliteConnection) -> QueryResult<usize> {
        use connection::Connection;
        conn.transaction(|| {
            let mut result = 0;
            for record in self.records {
                result += InsertStatement::new(
                    self.target,
                    record.values(),
                    self.operator,
                    self.returning,
                ).execute(conn)?;
            }
            Ok(result)
        })
    }
}

impl_query_id!(noop: InsertStatement<T, U, Op, Ret>);

impl<T, U, Op> AsQuery for InsertStatement<T, U, Op, NoReturningClause>
where
    T: Table,
    InsertStatement<T, U, Op, ReturningClause<T::AllColumns>>: Query,
{
    type SqlType = <Self::Query as Query>::SqlType;
    type Query = InsertStatement<T, U, Op, ReturningClause<T::AllColumns>>;

    fn as_query(self) -> Self::Query {
        self.returning(T::all_columns())
    }
}

impl<T, U, Op, Ret> Query for InsertStatement<T, U, Op, ReturningClause<Ret>>
where
    Ret: Expression + SelectableExpression<T> + NonAggregate,
{
    type SqlType = Ret::SqlType;
}

impl<T, U, Op> InsertStatement<T, U, Op> {
    /// Specify what expression is returned after execution of the `insert`.
    /// # Examples
    ///
    /// ### Inserting records:
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("../doctest_setup.rs");
    /// #
    /// # table! {
    /// #     users {
    /// #         id -> Integer,
    /// #         name -> VarChar,
    /// #     }
    /// # }
    /// #
    /// # #[cfg(feature = "postgres")]
    /// # fn main() {
    /// #     use self::users::dsl::*;
    /// #     let connection = establish_connection();
    /// let new_users = vec![
    ///     NewUser { name: "Timmy".to_string(), },
    ///     NewUser { name: "Jimmy".to_string(), },
    /// ];
    ///
    /// let inserted_names = diesel::insert_into(users)
    ///     .values(&new_users)
    ///     .returning(name)
    ///     .get_results(&connection);
    /// assert_eq!(Ok(vec!["Timmy".to_string(), "Jimmy".to_string()]), inserted_names);
    /// # }
    /// # #[cfg(not(feature = "postgres"))]
    /// # fn main() {}
    /// ```
    pub fn returning<E>(self, returns: E) -> InsertStatement<T, U, Op, ReturningClause<E>>
    where
        InsertStatement<T, U, Op, ReturningClause<E>>: Query,
    {
        InsertStatement::new(
            self.target,
            self.records,
            self.operator,
            ReturningClause(returns),
        )
    }
}

#[derive(Debug, Copy, Clone)]
#[doc(hidden)]
pub struct Insert;

impl<DB: Backend> QueryFragment<DB> for Insert {
    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
        out.push_sql("INSERT");
        Ok(())
    }
}

impl_query_id!(Insert);

#[derive(Debug, Copy, Clone)]
#[doc(hidden)]
pub struct Replace;

#[cfg(feature = "sqlite")]
impl QueryFragment<Sqlite> for Replace {
    fn walk_ast(&self, mut out: AstPass<Sqlite>) -> QueryResult<()> {
        out.push_sql("REPLACE");
        Ok(())
    }
}

#[cfg(feature = "mysql")]
impl QueryFragment<Mysql> for Replace {
    fn walk_ast(&self, mut out: AstPass<Mysql>) -> QueryResult<()> {
        out.push_sql("REPLACE");
        Ok(())
    }
}

impl_query_id!(Replace);

/// Marker trait to indicate that no additional operations have been added
/// to a record for insert. Used to prevent things like
/// `insert(&vec![user.on_conflict_do_nothing(), user2.on_conflict_do_nothing()])`
/// from compiling.
pub trait UndecoratedInsertRecord<Table> {}

impl<'a, T, Tab> UndecoratedInsertRecord<Tab> for &'a T
where
    T: ?Sized + UndecoratedInsertRecord<Tab>,
{
}

impl<T, U> UndecoratedInsertRecord<T::Table> for ColumnInsertValue<T, U>
where
    T: Column,
{
}

impl<T, Table> UndecoratedInsertRecord<Table> for [T]
where
    T: UndecoratedInsertRecord<Table>,
{
}

impl<T, Table> UndecoratedInsertRecord<Table> for Vec<T>
where
    [T]: UndecoratedInsertRecord<Table>,
{
}

impl<Lhs, Rhs> UndecoratedInsertRecord<Lhs::Table> for Eq<Lhs, Rhs>
where
    Lhs: Column,
{
}

impl<Lhs, Rhs, Tab> UndecoratedInsertRecord<Tab> for Option<Eq<Lhs, Rhs>>
where
    Eq<Lhs, Rhs>: UndecoratedInsertRecord<Tab>,
{
}

#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct DefaultValues;

impl<DB: Backend> CanInsertInSingleQuery<DB> for DefaultValues {
    fn rows_to_insert(&self) -> usize {
        1
    }
}

impl<'a, Tab> Insertable<Tab> for &'a DefaultValues {
    type Values = DefaultValues;

    fn values(self) -> Self::Values {
        *self
    }
}

impl<Tab, DB> InsertValues<Tab, DB> for DefaultValues
where
    Tab: Table,
    DB: Backend + Any,
{
    fn column_names(&self, _: &mut DB::QueryBuilder) -> QueryResult<()> {
        Ok(())
    }

    fn walk_ast(&self, _: AstPass<DB>) -> QueryResult<()> {
        Ok(())
    }

    #[cfg(not(feature = "mysql"))]
    fn is_noop(&self) -> bool {
        true
    }

    #[cfg(feature = "mysql")]
    fn is_noop(&self) -> bool {
        // The syntax for this on MySQL is
        // INSERT INTO table () VALUES ()
        //
        // This is hacky, but it's the easiest way to get this done without a
        // deeper restructuring of this code.
        TypeId::of::<DB>() != TypeId::of::<::mysql::Mysql>()
    }
}
<|endoftext|>


<commit_before><commit_msg>remove unused<commit_after><|endoftext|>


<commit_before><commit_msg>Add unit test for parse_info_hash_test<commit_after><|endoftext|>


<commit_before><commit_msg>Clean up use statements to fix compiler warnings<commit_after><|endoftext|>


<commit_before>// (C)opyleft 2013,2014 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#![desc = "A fast Bloom filter implementation."]
#![license = "BSD"]
#![crate_id="bloomfilter#0.1"]
#![crate_type = "rlib"]
#![warn(non_camel_case_types, non_uppercase_statics, unnecessary_qualification, managed_heap_memory)]

extern crate collections;

use std::cmp;
use std::f64;
use std::hash::Hash;
use std::hash::sip::SipHasher;
use std::hash::Hasher;
use std::rand;
use collections::bitv;

#[cfg(test)]
use std::rand::Rng;

/// Bloom filter structure
pub struct Bloom {
    bitmap: bitv::Bitv,
    bitmap_bits: u64,
    k_num: uint,
    sips: [SipHasher, ..2]
}

impl Bloom {
/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: uint, items_count: uint) -> Bloom {
        assert!(bitmap_size > 0u && items_count > 0u);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = bitv::Bitv::new(bitmap_bits as uint, false);
        let sips = [ Bloom::sip_new(), Bloom::sip_new() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            sips: sips
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: uint, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: uint, fp_p: f64) -> uint {
        assert!(items_count > 0u);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = f64::consts::LN_2;
        let log2_2 = log2 * log2;
        ((items_count as f64) * fp_p.ln() / (-8.0 * log2_2)).ceil() as uint
    }

/// Record the presence of an item.
    pub fn set<T: Hash>(& mut self, item: T) {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T: Hash>(&self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T: Hash>(&mut self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: uint) -> uint {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * 2.0f64.ln()).ceil() as uint;
        cmp::max(k_num, 1)
    }

    fn bloom_hash<T: Hash>(&self, hashes: & mut [u64, ..2],
                  item: &T, k_i: uint) -> u64 {
        if k_i < 2 {
            let sip = self.sips[k_i];
            let hash = sip.hash(item);
            hashes[k_i] = hash;
            hash
        } else {
            hashes[0] + (((k_i as u64) * hashes[1]) % 0xffffffffffffffc5)
        }
    }

    fn sip_new() -> SipHasher {
        let mut rng = rand::task_rng();
        SipHasher::new_with_keys(rand::Rand::rand(& mut rng),
                                 rand::Rand::rand(& mut rng))
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::task_rng().gen_iter::<u8>().take(16u).collect();
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::task_rng().gen_iter::<u8>().take(16u).collect();
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}
<commit_msg>crate_id is no more<commit_after>// (C)opyleft 2013,2014 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#![desc = "A fast Bloom filter implementation."]
#![license = "BSD"]
#![crate_name="bloomfilter"]
#![crate_type = "rlib"]
#![warn(non_camel_case_types, non_uppercase_statics, unnecessary_qualification, managed_heap_memory)]

extern crate collections;

use std::cmp;
use std::f64;
use std::hash::Hash;
use std::hash::sip::SipHasher;
use std::hash::Hasher;
use std::rand;
use collections::bitv;

#[cfg(test)]
use std::rand::Rng;

/// Bloom filter structure
pub struct Bloom {
    bitmap: bitv::Bitv,
    bitmap_bits: u64,
    k_num: uint,
    sips: [SipHasher, ..2]
}

impl Bloom {
/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: uint, items_count: uint) -> Bloom {
        assert!(bitmap_size > 0u && items_count > 0u);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = bitv::Bitv::new(bitmap_bits as uint, false);
        let sips = [ Bloom::sip_new(), Bloom::sip_new() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            sips: sips
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: uint, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: uint, fp_p: f64) -> uint {
        assert!(items_count > 0u);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = f64::consts::LN_2;
        let log2_2 = log2 * log2;
        ((items_count as f64) * fp_p.ln() / (-8.0 * log2_2)).ceil() as uint
    }

/// Record the presence of an item.
    pub fn set<T: Hash>(& mut self, item: T) {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T: Hash>(&self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T: Hash>(&mut self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: uint) -> uint {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * 2.0f64.ln()).ceil() as uint;
        cmp::max(k_num, 1)
    }

    fn bloom_hash<T: Hash>(&self, hashes: & mut [u64, ..2],
                  item: &T, k_i: uint) -> u64 {
        if k_i < 2 {
            let sip = self.sips[k_i];
            let hash = sip.hash(item);
            hashes[k_i] = hash;
            hash
        } else {
            hashes[0] + (((k_i as u64) * hashes[1]) % 0xffffffffffffffc5)
        }
    }

    fn sip_new() -> SipHasher {
        let mut rng = rand::task_rng();
        SipHasher::new_with_keys(rand::Rand::rand(& mut rng),
                                 rand::Rand::rand(& mut rng))
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::task_rng().gen_iter::<u8>().take(16u).collect();
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key: &Vec<u8> = &rand::task_rng().gen_iter::<u8>().take(16u).collect();
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}
<|endoftext|>


<commit_before><commit_msg>Add getter function for http_proxy<commit_after><|endoftext|>


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

use std::env;
use std::io::BufWriter;
use std::io::{self, Write};

fn main() {
    let os_args = env::args();
    let args: Vec<_> = os_args.collect();

    if args.len() != 4 {
        println!("usage : {} start numline width", args[0]);
        return;
    }

    let start_num = args[1].trim_right().parse::<u64>().unwrap_or(0);
    let stop_num = args[2].trim_right().parse::<u64>().unwrap_or(0);
    let width_num = args[3].trim_right().parse::<u64>().unwrap_or(0);

    gen_lines(start_num, stop_num, width_num);
}

fn gen_lines(start: u64, stop: u64, linewidth: u64) -> () {
    let string = gen_line(linewidth);

    let stdout = io::stdout();
    let mut buff = BufWriter::new(stdout);
    for x in start..start + stop + 1 {
        buff.write_fmt(format_args!("{:012} {}", x, string)).unwrap();
    }
}

fn gen_line(linewidth: u64) -> String {
    let mut string = String::new();

    let table = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
                 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
                 'w', 'x', 'y', 'z'];

    for x in 0..linewidth {
        string.push(table[x as usize % table.len()]);
    }
    string.push('\n');

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

use std::env;
use std::io::BufWriter;
use std::io::{self, Write};

fn main() {
    let os_args = env::args();
    let args: Vec<_> = os_args.collect();

    if args.len() != 4 {
        println!("usage : {} start numline width", args[0]);
        return;
    }

    let start_num = args[1].trim_end().parse::<u64>().unwrap_or(0);
    let stop_num = args[2].trim_end().parse::<u64>().unwrap_or(0);
    let width_num = args[3].trim_end().parse::<u64>().unwrap_or(0);

    gen_lines(start_num, stop_num, width_num);
}

fn gen_lines(start: u64, stop: u64, linewidth: u64) -> () {
    let string = gen_line(linewidth);

    let stdout = io::stdout();
    let mut buff = BufWriter::new(stdout);
    for x in start..start + stop + 1 {
        buff.write_fmt(format_args!("{:012} {}", x, string)).unwrap();
    }
}

fn gen_line(linewidth: u64) -> String {
    let mut string = String::new();

    let table = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
                 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
                 'w', 'x', 'y', 'z'];

    for x in 0..linewidth {
        string.push(table[x as usize % table.len()]);
    }
    string.push('\n');

    string
}
<|endoftext|>


<commit_before>// Copyright 2019 Jeremy Wall
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::ast::printer::*;
use crate::iter::OffsetStrIter;
use crate::parse::*;

fn assert_parse(input: &str) -> Vec<Statement> {
    parse(OffsetStrIter::new(input)).unwrap()
}

#[test]
fn test_simple_value_printing() {
    let input = "1;";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(0, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_simple_selector_printing() {
    let input = "foo.bar.quux;";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(0, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_simple_quoted_printing() {
    let input = "\"foo\";";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(0, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_escaped_quoted_printing() {
    let input = "\"f\\\\o\\\"o\";";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(0, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_empty_tuple_printing() {
    let input = "{};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_empty_list_printing() {
    let input = "[];";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_non_empty_tuple_printing() {
    let input = "{\n  foo = 1,\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_nested_empty_tuple_printing() {
    let input = "{\n  foo = {},\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_list_nested_empty_tuple_printing() {
    let input = "[\n  {},\n];";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_nested_non_empty_tuple_printing() {
    let input = "{\n  foo = {\n    bar = 1,\n  },\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_nested_non_empty_list_printing() {
    let input = "[\n  [\n    1,\n  ],\n];";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_simple_quoted_field_tuple_printing() {
    let input = "{\n  \"foo\" = {\n    bar = 1,\n  },\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(
        String::from_utf8(buffer).unwrap(),
        format!("{}\n", "{\n  foo = {\n    bar = 1,\n  },\n};")
    );
}

#[test]
fn test_special_quoted_field_tuple_printing() {
    let input = "{\n  \"foo bar\" = {\n    bar = 1,\n  },\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_let_statement_printing() {
    let input = "let tpl = {\n  \"foo bar\" = {\n    bar = 1,\n  },\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_call_expr_printing() {
    let input = "call(\n  foo,\n  bar,\n);";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_call_expr_one_arg_printing() {
    let input = "call(foo);";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_copy_expr_printing() {
    let input = "copy{\n  foo = 1,\n  bar = 2,\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_copy_expr_one_arg_printing() {
    let input = "copy{\n  foo = 1,\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_out_expr_printing() {
    let input = "out json {\n  foo = 1,\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_select_expr_no_default_printing() {
    let input = "select true, {\n  true = 1,\n  false = 2,\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_select_expr_with_default_printing() {
    let input = "select true, 3, {\n  true = 1,\n  false = 2,\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_not_expr_printing() {
    let input = "not true;";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_module_no_out_expr_printing() {
    let input = "let m = module {
  hostname = \"\",
  mem = 2048,
  cpu = 2,
} => {
  let config = {
    hostname = mod.hostname,
    \"memory_size\" = mod.mem,
    \"cpu_count\" = mod.cpu,
  };
};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_module_with_out_expr_printing() {
    let input = "let m = module {
  hostname = \"\",
  mem = 2048,
  cpu = 2,
} => (config) {
  let config = {
    hostname = mod.hostname,
    \"memory_size\" = mod.mem,
    \"cpu_count\" = mod.cpu,
  };
};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_func_expr_printing() {
    let input = "let f = func (foo, bar) => {
  foo = foo,
  bar = bar,
};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_func_expr_single_arg_printing() {
    let input = "let f = func (foo) => {
  foo = foo,
};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_format_expr_single_arg_printing() {
    let input = "\"what? @{item.foo}\" % {
  foo = 1,
};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_format_expr_list_arg_printing() {
    let input = "\"what? @ @\" % (
  1,
  2);";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}
<commit_msg>MAINT: Tests for fail and trace expressions.<commit_after>// Copyright 2019 Jeremy Wall
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::ast::printer::*;
use crate::iter::OffsetStrIter;
use crate::parse::*;

fn assert_parse(input: &str) -> Vec<Statement> {
    parse(OffsetStrIter::new(input)).unwrap()
}

#[test]
fn test_simple_value_printing() {
    let input = "1;";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(0, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_simple_selector_printing() {
    let input = "foo.bar.quux;";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(0, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_simple_quoted_printing() {
    let input = "\"foo\";";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(0, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_escaped_quoted_printing() {
    let input = "\"f\\\\o\\\"o\";";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(0, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_empty_tuple_printing() {
    let input = "{};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_empty_list_printing() {
    let input = "[];";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_non_empty_tuple_printing() {
    let input = "{\n  foo = 1,\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_nested_empty_tuple_printing() {
    let input = "{\n  foo = {},\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_list_nested_empty_tuple_printing() {
    let input = "[\n  {},\n];";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_nested_non_empty_tuple_printing() {
    let input = "{\n  foo = {\n    bar = 1,\n  },\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_nested_non_empty_list_printing() {
    let input = "[\n  [\n    1,\n  ],\n];";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_simple_quoted_field_tuple_printing() {
    let input = "{\n  \"foo\" = {\n    bar = 1,\n  },\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(
        String::from_utf8(buffer).unwrap(),
        format!("{}\n", "{\n  foo = {\n    bar = 1,\n  },\n};")
    );
}

#[test]
fn test_special_quoted_field_tuple_printing() {
    let input = "{\n  \"foo bar\" = {\n    bar = 1,\n  },\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_let_statement_printing() {
    let input = "let tpl = {\n  \"foo bar\" = {\n    bar = 1,\n  },\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_call_expr_printing() {
    let input = "call(\n  foo,\n  bar,\n);";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_call_expr_one_arg_printing() {
    let input = "call(foo);";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_copy_expr_printing() {
    let input = "copy{\n  foo = 1,\n  bar = 2,\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_copy_expr_one_arg_printing() {
    let input = "copy{\n  foo = 1,\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_out_expr_printing() {
    let input = "out json {\n  foo = 1,\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_select_expr_no_default_printing() {
    let input = "select true, {\n  true = 1,\n  false = 2,\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_select_expr_with_default_printing() {
    let input = "select true, 3, {\n  true = 1,\n  false = 2,\n};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_not_expr_printing() {
    let input = "not true;";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_fail_expr_printing() {
    let input = "fail \"AHHh\";";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_trace_expr_printing() {
    let input = "TRACE \"AHHh\";";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_module_no_out_expr_printing() {
    let input = "let m = module {
  hostname = \"\",
  mem = 2048,
  cpu = 2,
} => {
  let config = {
    hostname = mod.hostname,
    \"memory_size\" = mod.mem,
    \"cpu_count\" = mod.cpu,
  };
};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_module_with_out_expr_printing() {
    let input = "let m = module {
  hostname = \"\",
  mem = 2048,
  cpu = 2,
} => (config) {
  let config = {
    hostname = mod.hostname,
    \"memory_size\" = mod.mem,
    \"cpu_count\" = mod.cpu,
  };
};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_func_expr_printing() {
    let input = "let f = func (foo, bar) => {
  foo = foo,
  bar = bar,
};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_func_expr_single_arg_printing() {
    let input = "let f = func (foo) => {
  foo = foo,
};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_format_expr_single_arg_printing() {
    let input = "\"what? @{item.foo}\" % {
  foo = 1,
};";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}

#[test]
fn test_format_expr_list_arg_printing() {
    let input = "\"what? @ @\" % (
  1,
  2);";
    let stmts = assert_parse(input);
    let mut buffer: Vec<u8> = Vec::new();
    let mut printer = AstPrinter::new(2, &mut buffer);
    printer.render(&stmts);
    assert!(printer.err.is_none());
    assert_eq!(String::from_utf8(buffer).unwrap(), format!("{}\n", input));
}
<|endoftext|>


<commit_before>use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{self, BasicBlock, Location};
use rustc_middle::ty::TyCtxt;
use rustc_span::Span;

use super::ops::{self, NonConstOp};
use super::qualifs::{NeedsDrop, Qualif};
use super::validation::Qualifs;
use super::ConstCx;

/// Returns `true` if we should use the more precise live drop checker that runs after drop
/// elaboration.
pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool {
    // Const-stable functions must always use the stable live drop checker.
    if ccx.is_const_stable_const_fn() {
        return false;
    }

    ccx.tcx.features().const_precise_live_drops
}

/// Look for live drops in a const context.
///
/// This is separate from the rest of the const checking logic because it must run after drop
/// elaboration.
pub fn check_live_drops(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) {
    let def_id = body.source.def_id().expect_local();
    let const_kind = tcx.hir().body_const_context(def_id);
    if const_kind.is_none() {
        return;
    }

    let ccx = ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def_id) };
    if !checking_enabled(&ccx) {
        return;
    }

    let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() };

    visitor.visit_body(body);
}

struct CheckLiveDrops<'mir, 'tcx> {
    ccx: &'mir ConstCx<'mir, 'tcx>,
    qualifs: Qualifs<'mir, 'tcx>,
}

// So we can access `body` and `tcx`.
impl std::ops::Deref for CheckLiveDrops<'mir, 'tcx> {
    type Target = ConstCx<'mir, 'tcx>;

    fn deref(&self) -> &Self::Target {
        &self.ccx
    }
}

impl CheckLiveDrops<'mir, 'tcx> {
    fn check_live_drop(&self, span: Span) {
        ops::LiveDrop { dropped_at: None }.build_error(self.ccx, span).emit();
    }
}

impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> {
    fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &mir::BasicBlockData<'tcx>) {
        trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup);

        // Ignore drop terminators in cleanup blocks.
        if block.is_cleanup {
            return;
        }

        self.super_basic_block_data(bb, block);
    }

    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
        trace!("visit_terminator: terminator={:?} location={:?}", terminator, location);

        match &terminator.kind {
            mir::TerminatorKind::Drop { place: dropped_place, .. } => {
                let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
                if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
                    return;
                }

                if dropped_place.is_indirect() {
                    self.check_live_drop(terminator.source_info.span);
                    return;
                }

                if self.qualifs.needs_drop(self.ccx, dropped_place.local, location) {
                    // Use the span where the dropped local was declared for the error.
                    let span = self.body.local_decls[dropped_place.local].source_info.span;
                    self.check_live_drop(span);
                }
            }

            mir::TerminatorKind::DropAndReplace { .. } => span_bug!(
                terminator.source_info.span,
                "`DropAndReplace` should be removed by drop elaboration",
            ),

            mir::TerminatorKind::Abort
            | mir::TerminatorKind::Call { .. }
            | mir::TerminatorKind::Assert { .. }
            | mir::TerminatorKind::FalseEdge { .. }
            | mir::TerminatorKind::FalseUnwind { .. }
            | mir::TerminatorKind::GeneratorDrop
            | mir::TerminatorKind::Goto { .. }
            | mir::TerminatorKind::InlineAsm { .. }
            | mir::TerminatorKind::Resume
            | mir::TerminatorKind::Return
            | mir::TerminatorKind::SwitchInt { .. }
            | mir::TerminatorKind::Unreachable
            | mir::TerminatorKind::Yield { .. } => {}
        }
    }
}
<commit_msg>Rollup merge of #83351 - RalfJung:precise-const-drop, r=oli-obk<commit_after>use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{self, BasicBlock, Location};
use rustc_middle::ty::TyCtxt;
use rustc_span::Span;

use super::ops::{self, NonConstOp};
use super::qualifs::{NeedsDrop, Qualif};
use super::validation::Qualifs;
use super::ConstCx;

/// Returns `true` if we should use the more precise live drop checker that runs after drop
/// elaboration.
pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool {
    // Const-stable functions must always use the stable live drop checker.
    if ccx.is_const_stable_const_fn() {
        return false;
    }

    ccx.tcx.features().const_precise_live_drops
}

/// Look for live drops in a const context.
///
/// This is separate from the rest of the const checking logic because it must run after drop
/// elaboration.
pub fn check_live_drops(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) {
    let def_id = body.source.def_id().expect_local();
    let const_kind = tcx.hir().body_const_context(def_id);
    if const_kind.is_none() {
        return;
    }

    let ccx = ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def_id) };
    if !checking_enabled(&ccx) {
        return;
    }

    let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() };

    visitor.visit_body(body);
}

struct CheckLiveDrops<'mir, 'tcx> {
    ccx: &'mir ConstCx<'mir, 'tcx>,
    qualifs: Qualifs<'mir, 'tcx>,
}

// So we can access `body` and `tcx`.
impl std::ops::Deref for CheckLiveDrops<'mir, 'tcx> {
    type Target = ConstCx<'mir, 'tcx>;

    fn deref(&self) -> &Self::Target {
        &self.ccx
    }
}

impl CheckLiveDrops<'mir, 'tcx> {
    fn check_live_drop(&self, span: Span) {
        ops::LiveDrop { dropped_at: None }.build_error(self.ccx, span).emit();
    }
}

impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> {
    fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &mir::BasicBlockData<'tcx>) {
        trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup);

        // Ignore drop terminators in cleanup blocks.
        if block.is_cleanup {
            return;
        }

        self.super_basic_block_data(bb, block);
    }

    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
        trace!("visit_terminator: terminator={:?} location={:?}", terminator, location);

        match &terminator.kind {
            mir::TerminatorKind::Drop { place: dropped_place, .. } => {
                let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
                if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
                    bug!(
                        "Drop elaboration left behind a Drop for a type that does not need dropping"
                    );
                }

                if dropped_place.is_indirect() {
                    self.check_live_drop(terminator.source_info.span);
                    return;
                }

                // Drop elaboration is not precise enough to accept code like
                // `src/test/ui/consts/control-flow/drop-pass.rs`; e.g., when an `Option<Vec<T>>` is
                // initialized with `None` and never changed, it still emits drop glue.
                // Hence we additionally check the qualifs here to allow more code to pass.
                if self.qualifs.needs_drop(self.ccx, dropped_place.local, location) {
                    // Use the span where the dropped local was declared for the error.
                    let span = self.body.local_decls[dropped_place.local].source_info.span;
                    self.check_live_drop(span);
                }
            }

            mir::TerminatorKind::DropAndReplace { .. } => span_bug!(
                terminator.source_info.span,
                "`DropAndReplace` should be removed by drop elaboration",
            ),

            mir::TerminatorKind::Abort
            | mir::TerminatorKind::Call { .. }
            | mir::TerminatorKind::Assert { .. }
            | mir::TerminatorKind::FalseEdge { .. }
            | mir::TerminatorKind::FalseUnwind { .. }
            | mir::TerminatorKind::GeneratorDrop
            | mir::TerminatorKind::Goto { .. }
            | mir::TerminatorKind::InlineAsm { .. }
            | mir::TerminatorKind::Resume
            | mir::TerminatorKind::Return
            | mir::TerminatorKind::SwitchInt { .. }
            | mir::TerminatorKind::Unreachable
            | mir::TerminatorKind::Yield { .. } => {}
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>updating docs<commit_after><|endoftext|>


<commit_before><commit_msg>Unnormalize Morten's matrix elements<commit_after><|endoftext|>


<commit_before><commit_msg>remove clone<commit_after><|endoftext|>