<commit_before>//!
//! The API for communicating with devices.
//!
//! This API is provided as Traits to be implemented:
//!
//! - by the low-level layers of the FoxBox, including the adapters;
//! - by test suites and tools that need to simulate connected devices.
//!
//! In turn, this API is used to implement:
//!
//! - the public-facing REST and WebSocket API;
//! - the rules API (ThinkerBell).
//!
//!

use devices::*;
use requests::*;
use values::Value;

/// An error produced by one of the APIs in this module.
pub enum Error {
    /// There is no such node connected to the Foxbox, even indirectly.
    NoSuchNode(NodeId),

    /// There is no such service connected to the Foxbox, even indirectly.
    NoSuchService(ServiceId),

    /// Attempting to set a value with the wrong type
    TypeError,
}

/// An event during watching.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum WatchEvent {
    /// A new value is available.
    Value {
        /// The service that sent the value.
        from: ServiceId,

        /// The actual value.
        value: Value
    },

    /// The set of devices being watched has changed, typically either
    /// because a tag was edited or because a device was
    /// removed. Payload is the id of the device that was removed.
    InputRemoved(ServiceId),

    /// The set of devices being watched has changed, typically either
    /// because a tag was edited or because a device was
    /// added. Payload is the id of the device that was added.
    InputAdded(ServiceId),
}

/// The public API.
pub trait API {
    /// Get the metadata on nodes matching some conditions.
    ///
    /// A call to `API::get_nodes(vec![req1, req2, ...])` will return
    /// the metadata on all nodes matching _either_ `req1` or `req2`
    /// or ...
    ///
    /// # REST API
    ///
    /// `GET /api/v1/nodes`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to a `Vec<NodeRequest>`. See
    /// the implementation of `NodeRequest` for details.
    ///
    /// ### Example
    ///
    /// Request all doors in the entrance (tags `door`, `entrance`)
    /// that support output service `OpenClose`
    ///
    /// ```json
    /// [{
    ///   "tags": ["entrance", "door"],
    ///   "inputs": [
    ///     {
    ///       "kind": {
    ///         "Exactly": {
    ///           "OpenClose": []
    ///         }
    ///       }
    ///     }
    ///   ]
    /// }]
    /// ```
    ///
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing an array of `Node`. See the implementation
    /// of `Node` for details.
    ///
    /// ### Example
    ///
    /// ```json
    /// [{
    ///   "tags": ["entrance", "door", "somevendor"],
    ///   "id: "some-node-id",
    ///   "inputs": [],
    ///   "outputs": [
    ///     "tags": [...],
    ///     "id": "some-service-id",
    ///     "node": "some-node-id",
    ///     "last_seen": "some-date",
    ///     "mechanism": {
    ///       "Output":  {
    ///         "kind": {
    ///           "OnOff": []
    ///         },
    ///         "push": [5000],
    ///         "updated": "some-date",
    ///       }
    ///     }
    ///   ]
    /// }]
    /// ```
    fn get_nodes(&Vec<NodeRequest>) -> Vec<Node>;

    /// Label a set of nodes with a set of tags.
    ///
    /// A call to `API::put_node_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will label all the nodes matching _either_ `req1` or
    /// `req2` or ... with `tag1`, ... and return the number of nodes
    /// matching any of the requests.
    ///
    /// Some of the nodes may already be labelled with `tag1`, or
    /// `tag2`, ... They will not change state. They are counted in
    /// the resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if nodes
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `POST /api/v1/nodes/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<NodeRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON string representing a number.
    fn put_node_tag(set: &Vec<NodeRequest>, tags: &Vec<String>) -> usize;

    /// Remove a set of tags from a set of nodes.
    ///
    /// A call to `API::delete_node_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will remove from all the nodes matching _either_ `req1` or
    /// `req2` or ... all of the tags `tag1`, ... and return the number of nodes
    /// matching any of the requests.
    ///
    /// Some of the nodes may not be labelled with `tag1`, or `tag2`,
    /// ... They will not change state. They are counted in the
    /// resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if nodes
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `DELETE /api/v1/nodes/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<NodeRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn delete_node_tag(set: &Vec<NodeRequest>, tags: String) -> usize;

    /// Get a list of inputs matching some conditions
    ///
    /// # REST API
    ///
    /// `GET /api/v1/services`
    fn get_input_services(&Vec<InputRequest>) -> Vec<Service<Input>>;
    fn get_output_services(&Vec<OutputRequest>) -> Vec<Service<Output>>;

    /// Label a set of services with a set of tags.
    ///
    /// A call to `API::put_{input, output}_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will label all the services matching _either_ `req1` or
    /// `req2` or ... with `tag1`, ... and return the number of services
    /// matching any of the requests.
    ///
    /// Some of the services may already be labelled with `tag1`, or
    /// `tag2`, ... They will not change state. They are counted in
    /// the resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if services
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `POST /api/v1/services/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<InputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    /// or
    /// ```rust
    /// {
    ///   set: Vec<OutputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn put_input_tag(&Vec<InputRequest>, &Vec<String>) -> usize;
    fn put_output_tag(&Vec<OutputRequest>, &Vec<String>) -> usize;

    /// Remove a set of tags from a set of services.
    ///
    /// A call to `API::delete_{input, output}_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will remove from all the services matching _either_ `req1` or
    /// `req2` or ... all of the tags `tag1`, ... and return the number of services
    /// matching any of the requests.
    ///
    /// Some of the services may not be labelled with `tag1`, or `tag2`,
    /// ... They will not change state. They are counted in the
    /// resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if services
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `DELETE /api/v1/services/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<InputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    /// or
    /// ```rust
    /// {
    ///   set: Vec<OutputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn delete_input_tag(&Vec<InputRequest>, &Vec<String>) -> usize;
    fn delete_output_tag(&Vec<InputRequest>, &Vec<String>) -> usize;

    /// Read the latest value from a set of services
    ///
    /// # REST API
    ///
    /// `GET /api/v1/services/value`
    fn get_service_value(&Vec<InputRequest>) -> Vec<(ServiceId, Result<Value, Error>)>;

    /// Send one value to a set of services
    ///
    /// # REST API
    ///
    /// `POST /api/v1/services/value`
    fn put_service_value(&Vec<OutputRequest>, Value) -> Vec<(ServiceId, Result<(), Error>)>;

    /// Watch for any change
    ///
    /// # WebSocket API
    ///
    /// `/api/v1/services/watch`
    fn register_service_watch<F>(Vec<WatchOptions>, cb: F) -> Self::WatchGuard
        where F: FnMut(WatchEvent) + Send + 'static;

    /// A value that causes a disconnection once it is dropped.
    type WatchGuard;
}

/// Options for watching changes in one or more services.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct WatchOptions {
    /// The set of inputs to watch. Note that the actual inputs in the
    /// set may change over time.
    source: InputRequest,

    /// If `true`, watch as new values become available.
    should_watch_values: bool,

    /// If `true`, watch as nodes are connected/disconnected.
    should_watch_topology: bool,
}

impl WatchOptions {
    pub fn new() -> Self {
        WatchOptions {
            source: InputRequest::new(),
            should_watch_values: false,
            should_watch_topology: false,
        }
    }

    /// Restrict to input services in a given set.
    ///
    /// Also note that the actual input services that are part of the
    /// set may change with time, for instance if devices are added
    /// ore removed.  The request _is live_, i.e. the service watch
    /// will continue watching any input services that match `req`.
    pub fn with_inputs(self, req: InputRequest) -> Self {
        WatchOptions {
            source: self.source.and(req),
            ..self
        }
    }

    pub fn with_watch_values(self, should: bool) -> Self {
        WatchOptions {
            should_watch_values: should,
            ..self
        }
    }

    pub fn with_watch_topology(self, should: bool) -> Self {
        WatchOptions {
            should_watch_topology: should,
            ..self
        }
    }
}
<commit_msg>[fxbox/taxonomy] API::Error now supports Debug, Serialize, Deserialize, Clone<commit_after>//!
//! The API for communicating with devices.
//!
//! This API is provided as Traits to be implemented:
//!
//! - by the low-level layers of the FoxBox, including the adapters;
//! - by test suites and tools that need to simulate connected devices.
//!
//! In turn, this API is used to implement:
//!
//! - the public-facing REST and WebSocket API;
//! - the rules API (ThinkerBell).
//!
//!

use devices::*;
use requests::*;
use values::Value;

/// An error produced by one of the APIs in this module.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Error {
    /// There is no such node connected to the Foxbox, even indirectly.
    NoSuchNode(NodeId),

    /// There is no such service connected to the Foxbox, even indirectly.
    NoSuchService(ServiceId),

    /// Attempting to set a value with the wrong type
    TypeError,
}

/// An event during watching.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum WatchEvent {
    /// A new value is available.
    Value {
        /// The service that sent the value.
        from: ServiceId,

        /// The actual value.
        value: Value
    },

    /// The set of devices being watched has changed, typically either
    /// because a tag was edited or because a device was
    /// removed. Payload is the id of the device that was removed.
    InputRemoved(ServiceId),

    /// The set of devices being watched has changed, typically either
    /// because a tag was edited or because a device was
    /// added. Payload is the id of the device that was added.
    InputAdded(ServiceId),
}

/// The public API.
pub trait API {
    /// Get the metadata on nodes matching some conditions.
    ///
    /// A call to `API::get_nodes(vec![req1, req2, ...])` will return
    /// the metadata on all nodes matching _either_ `req1` or `req2`
    /// or ...
    ///
    /// # REST API
    ///
    /// `GET /api/v1/nodes`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to a `Vec<NodeRequest>`. See
    /// the implementation of `NodeRequest` for details.
    ///
    /// ### Example
    ///
    /// Request all doors in the entrance (tags `door`, `entrance`)
    /// that support output service `OpenClose`
    ///
    /// ```json
    /// [{
    ///   "tags": ["entrance", "door"],
    ///   "inputs": [
    ///     {
    ///       "kind": {
    ///         "Exactly": {
    ///           "OpenClose": []
    ///         }
    ///       }
    ///     }
    ///   ]
    /// }]
    /// ```
    ///
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing an array of `Node`. See the implementation
    /// of `Node` for details.
    ///
    /// ### Example
    ///
    /// ```json
    /// [{
    ///   "tags": ["entrance", "door", "somevendor"],
    ///   "id: "some-node-id",
    ///   "inputs": [],
    ///   "outputs": [
    ///     "tags": [...],
    ///     "id": "some-service-id",
    ///     "node": "some-node-id",
    ///     "last_seen": "some-date",
    ///     "mechanism": {
    ///       "Output":  {
    ///         "kind": {
    ///           "OnOff": []
    ///         },
    ///         "push": [5000],
    ///         "updated": "some-date",
    ///       }
    ///     }
    ///   ]
    /// }]
    /// ```
    fn get_nodes(&Vec<NodeRequest>) -> Vec<Node>;

    /// Label a set of nodes with a set of tags.
    ///
    /// A call to `API::put_node_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will label all the nodes matching _either_ `req1` or
    /// `req2` or ... with `tag1`, ... and return the number of nodes
    /// matching any of the requests.
    ///
    /// Some of the nodes may already be labelled with `tag1`, or
    /// `tag2`, ... They will not change state. They are counted in
    /// the resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if nodes
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `POST /api/v1/nodes/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<NodeRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON string representing a number.
    fn put_node_tag(set: &Vec<NodeRequest>, tags: &Vec<String>) -> usize;

    /// Remove a set of tags from a set of nodes.
    ///
    /// A call to `API::delete_node_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will remove from all the nodes matching _either_ `req1` or
    /// `req2` or ... all of the tags `tag1`, ... and return the number of nodes
    /// matching any of the requests.
    ///
    /// Some of the nodes may not be labelled with `tag1`, or `tag2`,
    /// ... They will not change state. They are counted in the
    /// resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if nodes
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `DELETE /api/v1/nodes/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<NodeRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn delete_node_tag(set: &Vec<NodeRequest>, tags: String) -> usize;

    /// Get a list of inputs matching some conditions
    ///
    /// # REST API
    ///
    /// `GET /api/v1/services`
    fn get_input_services(&Vec<InputRequest>) -> Vec<Service<Input>>;
    fn get_output_services(&Vec<OutputRequest>) -> Vec<Service<Output>>;

    /// Label a set of services with a set of tags.
    ///
    /// A call to `API::put_{input, output}_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will label all the services matching _either_ `req1` or
    /// `req2` or ... with `tag1`, ... and return the number of services
    /// matching any of the requests.
    ///
    /// Some of the services may already be labelled with `tag1`, or
    /// `tag2`, ... They will not change state. They are counted in
    /// the resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if services
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `POST /api/v1/services/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<InputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    /// or
    /// ```rust
    /// {
    ///   set: Vec<OutputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn put_input_tag(&Vec<InputRequest>, &Vec<String>) -> usize;
    fn put_output_tag(&Vec<OutputRequest>, &Vec<String>) -> usize;

    /// Remove a set of tags from a set of services.
    ///
    /// A call to `API::delete_{input, output}_tag(vec![req1, req2, ...], vec![tag1,
    /// ...])` will remove from all the services matching _either_ `req1` or
    /// `req2` or ... all of the tags `tag1`, ... and return the number of services
    /// matching any of the requests.
    ///
    /// Some of the services may not be labelled with `tag1`, or `tag2`,
    /// ... They will not change state. They are counted in the
    /// resulting `usize` nevertheless.
    ///
    /// Note that this call is _not live_. In other words, if services
    /// are added after the call, they will not be affected.
    ///
    /// # REST API
    ///
    /// `DELETE /api/v1/services/tag`
    ///
    /// ## Inputs
    ///
    /// Any JSON that can be deserialized to
    ///
    /// ```rust
    /// {
    ///   set: Vec<InputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    /// or
    /// ```rust
    /// {
    ///   set: Vec<OutputRequest>,
    ///   tags: Vec<String>,
    /// }
    /// ```
    ///
    /// ## Errors
    ///
    /// In case of syntax error, Error 400, accompanied with a
    /// somewhat human-readable JSON string detailing the error.
    ///
    /// ## Success
    ///
    /// A JSON representing a number.
    fn delete_input_tag(&Vec<InputRequest>, &Vec<String>) -> usize;
    fn delete_output_tag(&Vec<InputRequest>, &Vec<String>) -> usize;

    /// Read the latest value from a set of services
    ///
    /// # REST API
    ///
    /// `GET /api/v1/services/value`
    fn get_service_value(&Vec<InputRequest>) -> Vec<(ServiceId, Result<Value, Error>)>;

    /// Send one value to a set of services
    ///
    /// # REST API
    ///
    /// `POST /api/v1/services/value`
    fn put_service_value(&Vec<OutputRequest>, Value) -> Vec<(ServiceId, Result<(), Error>)>;

    /// Watch for any change
    ///
    /// # WebSocket API
    ///
    /// `/api/v1/services/watch`
    fn register_service_watch<F>(Vec<WatchOptions>, cb: F) -> Self::WatchGuard
        where F: FnMut(WatchEvent) + Send + 'static;

    /// A value that causes a disconnection once it is dropped.
    type WatchGuard;
}

/// Options for watching changes in one or more services.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct WatchOptions {
    /// The set of inputs to watch. Note that the actual inputs in the
    /// set may change over time.
    source: InputRequest,

    /// If `true`, watch as new values become available.
    should_watch_values: bool,

    /// If `true`, watch as nodes are connected/disconnected.
    should_watch_topology: bool,
}

impl WatchOptions {
    pub fn new() -> Self {
        WatchOptions {
            source: InputRequest::new(),
            should_watch_values: false,
            should_watch_topology: false,
        }
    }

    /// Restrict to input services in a given set.
    ///
    /// Also note that the actual input services that are part of the
    /// set may change with time, for instance if devices are added
    /// ore removed.  The request _is live_, i.e. the service watch
    /// will continue watching any input services that match `req`.
    pub fn with_inputs(self, req: InputRequest) -> Self {
        WatchOptions {
            source: self.source.and(req),
            ..self
        }
    }

    pub fn with_watch_values(self, should: bool) -> Self {
        WatchOptions {
            should_watch_values: should,
            ..self
        }
    }

    pub fn with_watch_topology(self, should: bool) -> Self {
        WatchOptions {
            should_watch_topology: should,
            ..self
        }
    }
}
<|endoftext|>


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

use types::*;

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Update {
    pub id: Integer,
    pub kind: UpdateKind,
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum UpdateKind {
    Message(Message),
    EditedMessage(Message),
    ChannelPost(Message),
    EditedChannelPost(Message),
//    InlineQuery(InlineQuery),
//    ChosenInlineResult(ChosenInlineResult),
//    CallbackQuery(OptionCallbackQuery),
    Unknown(RawUpdate)
}

impl Deserialize for Update {
    fn deserialize<D>(deserializer: D) -> Result<Update, D::Error> where D: Deserializer {
        let raw: RawUpdate = Deserialize::deserialize(deserializer)?;
        macro_rules! maybe_field {
            ($name:ident, $variant:ident) => {{
                if let Some(val) = raw.$name {
                    return Ok(Update {
                        id: raw.update_id,
                        kind: UpdateKind::$variant(val),
                    })
                }
            }}
        }

        maybe_field!(message, Message);
        maybe_field!(edited_message, EditedMessage);
        maybe_field!(channel_post, ChannelPost);
        maybe_field!(edited_channel_post, EditedChannelPost);
//        maybe_field!(inline_query, InlineQuery);
//        maybe_field!(chosen_inline_result, ChosenInlineResult);
//        maybe_field!(callback_query, CallbackQuery);

        Ok(Update {
            id: raw.update_id,
            kind: UpdateKind::Unknown(raw),
        })
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawUpdate {
    pub update_id: Integer,
    pub message: Option<Message>,
    pub edited_message: Option<Message>,
    pub channel_post: Option<Message>,
    pub edited_channel_post: Option<Message>,
//    pub inline_query: Option<InlineQuery>,
//    pub chosen_inline_result: Option<ChosenInlineResult>,
//    pub callback_query: Option<CallbackQuery>,
}
<commit_msg>refactor: hide UpdateKind::Unknown<commit_after>use serde::de::{Deserialize, Deserializer};

use types::*;

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Update {
    pub id: Integer,
    pub kind: UpdateKind,
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum UpdateKind {
    Message(Message),
    EditedMessage(Message),
    ChannelPost(Message),
    EditedChannelPost(Message),
//    InlineQuery(InlineQuery),
//    ChosenInlineResult(ChosenInlineResult),
//    CallbackQuery(OptionCallbackQuery),
    #[doc(hidden)]
    Unknown(RawUpdate)
}

impl Deserialize for Update {
    fn deserialize<D>(deserializer: D) -> Result<Update, D::Error> where D: Deserializer {
        let raw: RawUpdate = Deserialize::deserialize(deserializer)?;
        macro_rules! maybe_field {
            ($name:ident, $variant:ident) => {{
                if let Some(val) = raw.$name {
                    return Ok(Update {
                        id: raw.update_id,
                        kind: UpdateKind::$variant(val),
                    })
                }
            }}
        }

        maybe_field!(message, Message);
        maybe_field!(edited_message, EditedMessage);
        maybe_field!(channel_post, ChannelPost);
        maybe_field!(edited_channel_post, EditedChannelPost);
//        maybe_field!(inline_query, InlineQuery);
//        maybe_field!(chosen_inline_result, ChosenInlineResult);
//        maybe_field!(callback_query, CallbackQuery);

        Ok(Update {
            id: raw.update_id,
            kind: UpdateKind::Unknown(raw),
        })
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawUpdate {
    pub update_id: Integer,
    pub message: Option<Message>,
    pub edited_message: Option<Message>,
    pub channel_post: Option<Message>,
    pub edited_channel_post: Option<Message>,
//    pub inline_query: Option<InlineQuery>,
//    pub chosen_inline_result: Option<ChosenInlineResult>,
//    pub callback_query: Option<CallbackQuery>,
}
<|endoftext|>


<commit_before>
use event;
use select;
use builder;

use super::{ Select, SelectOnce, BuildElementStream, NoRestriction };

/// Select a substream at any level.
pub struct SelectAny<S, M, B>
where
    B: builder::BuildMut<BuildElementStream<S>>,
{
    select: Select<S, M, B, NoRestriction>,
}

impl<S, M, B> SelectAny<S, M, B>
where
    M: select::Selector,
    S: event::Stream,
    B: builder::BuildMut<BuildElementStream<S>>,
{
    pub(crate) fn new(stream: S, matcher: M, builder: B) -> SelectAny<S, M, B> {
        SelectAny {
            select: Select::new(stream, matcher, builder, NoRestriction),
        }
    }
}

impl<S, M, B> event::Stream for SelectAny<S, M, B>
where
    M: select::Selector,
    S: event::Stream,
    B: builder::BuildMut<BuildElementStream<S>>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.select.next_event()
    }
}

/// Select a substream at any level but only once.
pub struct SelectAnyOnce<S, M, B>
where
    B: builder::BuildOnce<BuildElementStream<S>>,
{
    select: SelectOnce<S, M, B, NoRestriction>,
}

impl<S, M, B> SelectAnyOnce<S, M, B>
where
    M: select::Selector,
    S: event::Stream,
    B: builder::BuildOnce<BuildElementStream<S>>,
{
    pub(crate) fn new(stream: S, matcher: M, builder: B) -> SelectAnyOnce<S, M, B> {
        SelectAnyOnce {
            select: SelectOnce::new(stream, matcher, builder, NoRestriction),
        }
    }
}

impl<S, M, B> event::Stream for SelectAnyOnce<S, M, B>
where
    M: select::Selector,
    S: event::Stream,
    B: builder::BuildOnce<BuildElementStream<S>>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.select.next_event()
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn select() {
        test_transform!(
            Default::default(),
            "
23
45",
            "
2399
4599",
            |html| html.select("b", |html| html.append_contents(99)),
        );
    }

    #[test]
    fn select_once() {
        test_transform!(
            Default::default(),
            "
23
45",
            "
2399
45",
            |html| html.select_once("b", |html| html.append_contents(99)),
        );
    }
}
<commit_msg>moved select to new test structure<commit_after>
use event;
use select;
use builder;

use super::{ Select, SelectOnce, BuildElementStream, NoRestriction };

/// Select a substream at any level.
pub struct SelectAny<S, M, B>
where
    B: builder::BuildMut<BuildElementStream<S>>,
{
    select: Select<S, M, B, NoRestriction>,
}

impl<S, M, B> SelectAny<S, M, B>
where
    M: select::Selector,
    S: event::Stream,
    B: builder::BuildMut<BuildElementStream<S>>,
{
    pub(crate) fn new(stream: S, matcher: M, builder: B) -> SelectAny<S, M, B> {
        SelectAny {
            select: Select::new(stream, matcher, builder, NoRestriction),
        }
    }
}

impl<S, M, B> event::Stream for SelectAny<S, M, B>
where
    M: select::Selector,
    S: event::Stream,
    B: builder::BuildMut<BuildElementStream<S>>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.select.next_event()
    }
}

/// Select a substream at any level but only once.
pub struct SelectAnyOnce<S, M, B>
where
    B: builder::BuildOnce<BuildElementStream<S>>,
{
    select: SelectOnce<S, M, B, NoRestriction>,
}

impl<S, M, B> SelectAnyOnce<S, M, B>
where
    M: select::Selector,
    S: event::Stream,
    B: builder::BuildOnce<BuildElementStream<S>>,
{
    pub(crate) fn new(stream: S, matcher: M, builder: B) -> SelectAnyOnce<S, M, B> {
        SelectAnyOnce {
            select: SelectOnce::new(stream, matcher, builder, NoRestriction),
        }
    }
}

impl<S, M, B> event::Stream for SelectAnyOnce<S, M, B>
where
    M: select::Selector,
    S: event::Stream,
    B: builder::BuildOnce<BuildElementStream<S>>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.select.next_event()
    }
}

#[cfg(test)]
mod tests {

    test_group!(select:
        "select all" => transform_test!(
            "
23
45",
            "
2399
4599",
            |html| html.select("b", |html| html.append_contents(99)),
        ),
        "ensure element stream" => transform_test!(
            "",
            "",
            |html| html.select("b", |html| html.into_boxed_element()),
        ),
    );

    test_group!(select_once:
        "select first" => transform_test!(
            "
23
45",
            "
2399
45",
            |html| html.select_once("b", |html| html.append_contents(99)),
        ),
        "ensure element stream" => transform_test!(
            "",
            "",
            |html| html.select_once("b", |html| html.into_boxed_element()),
        ),
    );
}
<|endoftext|>


<commit_before>extern crate proc_macro;
use proc_macro::TokenStream;
use proc_macro_error::*;
use proc_macro2::{Ident, Span};
use quote::*;
use std::collections::HashSet;

mod args;

mod bitpattern;

#[proc_macro_error]
#[proc_macro_attribute]
pub fn bitpattern(args: TokenStream, input: TokenStream) -> TokenStream {
    bitpattern::bitpattern(args, input)
}

mod bitfragment;

#[proc_macro_error]
#[proc_macro_attribute]
pub fn bitfragment(args: TokenStream, input: TokenStream) -> TokenStream {
    bitfragment::bitfragment(args, input)
}

fn parse_multi_string_attr_helper<T, F>(attrs: &[syn::Attribute], attr_name: &str, cb: F)
    -> std::iter::Map<std::vec::IntoIter<syn::LitStr>, F>
    where F: FnMut(syn::LitStr) -> T {

    let mut ret = Vec::new();
    for attr in attrs {
        if attr.path.leading_colon.is_none() && attr.path.segments.len() == 1 &&
           attr.path.segments[0].ident.to_string() == attr_name {
            let attr_val = attr.parse_meta();
            if attr_val.is_err() {
                panic!("Failed to parse {} attribute", attr_name);
            }

            if let syn::Meta::NameValue(nameval) = attr_val.unwrap() {
                if let syn::Lit::Str(litstr) = nameval.lit {
                    ret.push(litstr);
                } else {
                    panic!("{} attribute must be set to a string", attr_name)
                }
            } else {
                panic!("Malformed {} attribute", attr_name);
            }
        }
    }

    ret.into_iter().map(cb)
}

#[derive(Clone, Debug)]
enum BitTwiddlerFieldRef {
    Ident(Ident),
    Index(usize),
    Self_,
}

#[derive(Copy, Clone, Debug)]
enum BitTwiddlerObjType {
    Named,
    Unnamed,
    Enum,
}

impl BitTwiddlerFieldRef {
    fn to_string(&self) -> String {
        match self {
            BitTwiddlerFieldRef::Ident(id) => id.to_string().to_owned(),
            BitTwiddlerFieldRef::Index(idx) => format!("{}", idx),
            BitTwiddlerFieldRef::Self_ => "Enum".to_owned(),
        }
    }
}

#[derive(Debug)]
struct StringSplitter<'a> {
    str: &'a str,
    striter: std::str::CharIndices<'a>,
    // is_in_quote: bool,
    ended: bool,
    ungetbuf: Option<(usize, char)>,
}

impl<'a> StringSplitter<'a> {
    fn new(s: &'a str) -> Self {
        StringSplitter {
            str: s,
            striter: s.char_indices(),
            ended: false,
            ungetbuf: None,
        }
    }

    fn getchar(&mut self) -> Option<(usize, char)> {
        if self.ungetbuf.is_some() {
            let ret = self.ungetbuf;
            self.ungetbuf = None;
            ret
        } else {
            self.striter.next()
        }
    }

    fn ungetchar(&mut self, c: (usize, char)) {
        assert!(self.ungetbuf.is_none());
        self.ungetbuf = Some(c);
    }
}

impl<'a> Iterator for StringSplitter<'a> {
    type Item = &'a str;
    fn next(&mut self) -> Option<&'a str> {
        if self.ended {
            None
        } else {
            // Eat leading spaces
            let mut c = self.getchar();
            while c.is_some() && c.unwrap().1 == ' ' {
                c = self.getchar();
            }
            if c.is_none() {
                self.ended = true;
                return None;
            }
            // self.ungetchar(c.unwrap());

            // At this point we have at least 1 character and c is pointing to it
            let start_of_ret_idx = c.unwrap().0;
            let mut end_of_ret_idx = start_of_ret_idx;
            let mut is_in_quote = false;
            while c.is_some() {
                end_of_ret_idx = c.unwrap().0;
                if !is_in_quote {
                    if c.unwrap().1 == ' ' {
                        self.ungetchar(c.unwrap());
                        break;
                    }

                    if c.unwrap().1 == '\'' {
                        is_in_quote = true;
                    }

                    c = self.getchar();
                } else {
                    if c.unwrap().1 == '\'' {
                        is_in_quote = false;
                    }

                    c = self.getchar();
                }
            }
            // We have reached the end while returning the current item
            if c.is_none() {
                end_of_ret_idx = self.str.len();
            }

            Some(self.str.get(start_of_ret_idx..end_of_ret_idx).unwrap())
        }
    }
}

fn is_bool(ty: &syn::Type) -> bool {
    if let &syn::Type::Path(ref typep) = ty {
        if typep.qself.is_none() && typep.path.leading_colon.is_none() && typep.path.segments.len() == 1 &&
            typep.path.segments[0].ident.to_string() == "bool" {

            true
        } else {
            false
        }
    } else {
        false
    }
}

#[proc_macro_derive(BitTwiddler, attributes(bittwiddler, bittwiddler_field))]
pub fn bittwiddler(input: TokenStream) -> TokenStream {
    let input: syn::DeriveInput = syn::parse(input).unwrap();

    let main_bittwiddler_attribs = parse_multi_string_attr_helper(&input.attrs, "bittwiddler",
        |x| x.value()).collect::<Vec<_>>();

    let mut fields_and_attrs = Vec::new();

    let overall_type;

    match input.data {
        syn::Data::Struct(datastruct) => {
            match datastruct.fields {
                syn::Fields::Named(named) => {
                    for field in &named.named {
                        let id = field.ident.as_ref().unwrap();
                        let bittwiddler_field_attrs = parse_multi_string_attr_helper(&field.attrs, "bittwiddler_field",
                            |x| x.value()).collect::<Vec<_>>();

                        let is_bool = is_bool(&field.ty);

                        if bittwiddler_field_attrs.len() > 0 {
                            fields_and_attrs.push((BitTwiddlerFieldRef::Ident(id.clone()),
                                bittwiddler_field_attrs, is_bool, Some(field.ty.clone())));
                        }
                    }

                    overall_type = BitTwiddlerObjType::Named;
                },
                syn::Fields::Unnamed(unnamed) => {
                    for (idx, field) in unnamed.unnamed.iter().enumerate() {
                        let bittwiddler_field_attrs = parse_multi_string_attr_helper(&field.attrs, "bittwiddler_field",
                            |x| x.value()).collect::<Vec<_>>();

                        let is_bool = is_bool(&field.ty);

                        if bittwiddler_field_attrs.len() > 0 {
                            fields_and_attrs.push((BitTwiddlerFieldRef::Index(idx),
                                bittwiddler_field_attrs, is_bool, Some(field.ty.clone())));
                        }
                    }

                    overall_type = BitTwiddlerObjType::Unnamed;
                },
                syn::Fields::Unit => {
                    // This will be rejected later
                    overall_type = BitTwiddlerObjType::Named;
                },
            }
        },
        syn::Data::Enum(_dataenum) => {
            let bittwiddler_field_attrs = parse_multi_string_attr_helper(&input.attrs, "bittwiddler_field",
                |x| x.value()).collect::<Vec<_>>();

            if bittwiddler_field_attrs.len() > 0 {
                fields_and_attrs.push((BitTwiddlerFieldRef::Self_, bittwiddler_field_attrs, false, None));
            }

            overall_type = BitTwiddlerObjType::Enum;
        },
        _ => panic!("BitPattern must be used on a struct or enum")
    }

    let input_ident = input.ident;

    let mut all_tokens = quote!{};

    for bittwiddler_instance_attrib in main_bittwiddler_attribs {
        let mut attrib_split = StringSplitter::new(&bittwiddler_instance_attrib);
        let instance_name = attrib_split.next().unwrap();

        let instance_attribs = attrib_split.collect::<Vec<_>>();
        let mut instance_attribs_hash = HashSet::with_capacity(instance_attribs.len());
        for &x in &instance_attribs {
            instance_attribs_hash.insert(x);
        }

        let this_instance_attribs = fields_and_attrs.iter().map(|x|
            (x.0.clone(), x.1.iter().map(|y| StringSplitter::new(y).collect::<Vec<_>>()).filter(|z|
                z[0] == instance_name).collect::<Vec<_>>(), x.2, x.3.clone()));

        let mut errtype = None;
        for x in &instance_attribs {
            if x.starts_with("err=") {
                let mut errtype_tmp = x.split_at(4).1;
                if errtype_tmp.starts_with("'") {
                    if !errtype_tmp.ends_with("'") {
                        panic!("Malformed error type for {} on {}", instance_name, input_ident.to_string());
                    }

                    errtype_tmp = errtype_tmp.split_at(1).1;
                    errtype_tmp = errtype_tmp.split_at(errtype_tmp.len() - 1).0;
                }

                errtype = Some(syn::parse_str::<syn::TypeParam>(errtype_tmp).expect("Failed to parse err= attribute"));
            }
        }

        let mut dimensions = None;

        let encode_fn_ident = Ident::new(&format!("encode_{}", instance_name), Span::call_site());

        let mut encode_field_tokens = quote!{};

        let decode_fn_ident = Ident::new(&format!("decode_{}", instance_name), Span::call_site());

        let mut decode_field_tokens = quote!{};
        let mut decode_field_ids = Vec::new();

        let is_abs = instance_attribs_hash.contains("abs");

        for (field_id, field_locs, field_isbool, field_ty) in this_instance_attribs {
            if field_locs.len() == 0 {
                continue;
            }

            if field_locs.len() > 1 {
                panic!("{} has multiple bittwiddler_field for type {}", field_id.to_string(), instance_name);
            }
            let mut field_locs = &field_locs[0][1..];

            let mut needs_err = false;
            if field_locs[0] == "err" {
                needs_err = true;
                field_locs = &field_locs[1..];
            }

            let mut is_arr = false;
            if field_locs[0] == "arr" {
                is_arr = true;
                field_locs = &field_locs[1..];
            }

            if field_isbool && field_locs.len() != 1 {
                panic!("Field {} of {} on {} has too many locations for a boolean",
                    field_id.to_string(), instance_name, input_ident.to_string());
            }

            // Now we can actually generate code
            let mut encode_this_field = if !field_isbool {
                match field_id {
                    BitTwiddlerFieldRef::Ident(ref id) => {
                        quote! {
                            let x = self.#id.encode();
                        }
                    },
                    BitTwiddlerFieldRef::Index(idx) => {
                        let field_idx = syn::Index {
                            index: idx as u32,
                            // TODO: IDK wtf to do here?!
                            span: input_ident.span()
                        };
                        quote! {
                            let x = self.#field_idx.encode();
                        }
                    },
                    BitTwiddlerFieldRef::Self_ => {
                        quote! {
                            let x = self.encode();
                        }
                    }
                }
            } else {
                match field_id {
                    BitTwiddlerFieldRef::Ident(ref id) => {
                        quote! {
                            let x = self.#id;
                        }
                    },
                    BitTwiddlerFieldRef::Index(idx) => {
                        let field_idx = syn::Index {
                            index: idx as u32,
                            // TODO: IDK wtf to do here?!
                            span: input_ident.span()
                        };
                        quote! {
                            let x = self.#field_idx;
                        }
                    },
                    BitTwiddlerFieldRef::Self_ => {
                        unreachable!();
                    }
                }
            };

            let mut decode_this_field_locs = Vec::new();

            for (field_bit_i, loc) in field_locs.iter().enumerate() {
                let mut loc = *loc;
                let inv = loc.get(0..1) == Some("!");
                if inv {
                    loc = loc.split_at(1).1;
                }

                if loc == "T" || loc == "F" {
                    let inv_token = if inv {quote!{!}} else {quote!{}};
                    let tf = loc == "T";
                    // Shut up an unused variable warning
                    encode_this_field.append_all(quote! {
                        match x {
                            _ => {}
                        }
                    });
                    decode_this_field_locs.push(quote! {
                        #inv_token #tf
                    });
                } else {
                    let coords = loc.split('|').collect::<Vec<_>>();

                    if dimensions.is_none() {
                        dimensions = Some(coords.len());
                    } else {
                        if dimensions.unwrap() != coords.len() {
                            panic!("Instance {} on {} has mismatched dimensions", instance_name, input_ident.to_string());
                        }
                    }

                    let mut index_each_dim = Vec::with_capacity(coords.len());
                    for (dim_i, coord_str) in coords.iter().enumerate() {
                        let mirror_attrib = format!("mirror{}", dim_i);
                        let mirror = instance_attribs_hash.contains::<str>(&mirror_attrib);
                        let coord_i = coord_str.parse::<usize>().expect("Could not parse coordinate as number or T/F");

                        if mirror && is_abs {
                            panic!("Mirror and abs cannot be used at the same time");
                        }

                        if dimensions.unwrap() > 1 {
                            let dim_idx = syn::Index {
                                index: dim_i as u32,
                                // TODO: IDK wtf to do here?!
                                span: input_ident.span()
                            };

                            if mirror {
                                let mirror_ident = Ident::new(&format!("mirror_{}", dim_i), Span::call_site());
                                // mirror_idents.push(quote!{#mirror_ident: bool});
                                index_each_dim.push(quote! {
                                    (start_coord.#dim_idx as isize +
                                        (if #mirror_ident {-1} else {1}) * #coord_i as isize) as usize
                                });
                            } else if !is_abs {
                                index_each_dim.push(quote! {
                                    start_coord.#dim_idx + #coord_i
                                });
                            } else {
                                index_each_dim.push(quote! {
                                    #coord_i
                                });
                            }
                        } else {
                            if mirror {
                                let mirror_ident = Ident::new(&format!("mirror_{}", dim_i), Span::call_site());
                                // mirror_idents.push(quote!{#mirror_ident: bool});
                                index_each_dim.push(quote! {
                                    (start_coord as isize +
                                        (if #mirror_ident {-1} else {1}) * #coord_i as isize) as usize
                                });
                            } else if !is_abs {
                                index_each_dim.push(quote! {
                                    start_coord + #coord_i
                                });
                            } else {
                                index_each_dim.push(quote! {
                                    #coord_i
                                });
                            }
                        }
                    }

                    let index_each_dim2 = index_each_dim.clone();

                    let inv_token = if inv {quote!{!}} else {quote!{}};

                    if !field_isbool {
                        let field_bit_idx = syn::Index {
                            index: field_bit_i as u32,
                            // TODO: IDK wtf to do here?!
                            span: input_ident.span()
                        };

                        if !is_arr {
                            encode_this_field.append_all(quote! {
                                fuses[(#(#index_each_dim),*)] = #inv_token x.#field_bit_idx;
                            });
                        } else {
                            encode_this_field.append_all(quote! {
                                fuses[(#(#index_each_dim),*)] = #inv_token x[#field_bit_idx];
                            });
                        }
                    } else {
                        encode_this_field.append_all(quote! {
                            fuses[(#(#index_each_dim),*)] = #inv_token x;
                        });
                    }

                    decode_this_field_locs.push(quote! {
                        #inv_token fuses[(#(#index_each_dim2),*)]
                    });
                }
            }

            encode_field_tokens.append_all(encode_this_field);

            let mut decode_this_field = if !is_arr {
                if decode_this_field_locs.len() != 1 {
                    quote! {
                        let x = (#(#decode_this_field_locs),*);
                    }
                } else {
                    // Suppress warnings about extra parens
                    quote! {
                        let x = #(#decode_this_field_locs),*;
                    }
                }
            } else {
                quote! {
                    let x = &[#(#decode_this_field_locs),*];
                }
            };
            decode_this_field.append_all(if !field_isbool {
                match field_id {
                    BitTwiddlerFieldRef::Ident(ref id) => {
                        let ty = field_ty.unwrap();
                        decode_field_ids.push(id.clone());
                        if is_arr {
                            // Hack for now
                            quote! {
                                let #id = #ty::decode(x).unwrap();
                            }
                        } else if needs_err {
                            quote! {
                                let #id = #ty::decode(x)?;
                            }
                        } else {
                            quote! {
                                let #id = #ty::decode(x);
                            }
                        }
                    },
                    BitTwiddlerFieldRef::Index(idx) => {
                        let ty = field_ty.unwrap();
                        let id = Ident::new(&format!{"field{}", idx}, Span::call_site());
                        decode_field_ids.push(id.clone());
                        if is_arr {
                            // Hack for now
                            quote! {
                                let #id = #ty::decode(x).unwrap();
                            }
                        } else if needs_err {
                            quote! {
                                let #id = #ty::decode(x)?;
                            }
                        } else {
                            quote! {
                                let #id = #ty::decode(x);
                            }
                        }
                    },
                    BitTwiddlerFieldRef::Self_ => {
                        if is_arr {
                            // Hack for now
                            quote! {
                                let self_ = Self::decode(x).unwrap();
                            }
                        } else if needs_err {
                            quote! {
                                let self_ = Self::decode(x)?;
                            }
                        } else {
                            quote! {
                                let self_ = Self::decode(x);
                            }
                        }
                    }
                }
            } else {
                if needs_err {
                    panic!("Field {} of {} on {} has \"err\" flag, but it's a boolean",
                        field_id.to_string(), instance_name, input_ident.to_string());
                }
                match field_id {
                    BitTwiddlerFieldRef::Ident(ref id) => {
                        decode_field_ids.push(id.clone());
                        quote! {
                            let #id = x;
                        }
                    },
                    BitTwiddlerFieldRef::Index(idx) => {
                        let id = Ident::new(&format!{"field{}", idx}, Span::call_site());
                        decode_field_ids.push(id.clone());
                        quote! {
                            let #id = x;
                        }
                    },
                    BitTwiddlerFieldRef::Self_ => {
                        unreachable!();
                    }
                }
            });

            decode_field_tokens.append_all(decode_this_field);
        }

        if dimensions.is_none() {
            panic!("Instance {} on {} has zero fields", instance_name, input_ident.to_string());
        }

        let mut usize_idents = Vec::with_capacity(dimensions.unwrap());
        for _ in 0..dimensions.unwrap() {
            usize_idents.push(quote!{usize});
        }
        let mut usize_idents2 = Vec::with_capacity(dimensions.unwrap());
        for _ in 0..dimensions.unwrap() {
            usize_idents2.push(quote!{usize});
        }
        let mut usize_idents3 = Vec::with_capacity(dimensions.unwrap());
        for _ in 0..dimensions.unwrap() {
            usize_idents3.push(quote!{usize});
        }
        let mut usize_idents4 = Vec::with_capacity(dimensions.unwrap());
        for _ in 0..dimensions.unwrap() {
            usize_idents4.push(quote!{usize});
        }

        let mut mirror_idents = Vec::new();
        for dim_i in 0..dimensions.unwrap() {
            let mirror_attrib = format!("mirror{}", dim_i);
            let mirror = instance_attribs_hash.contains::<str>(&mirror_attrib);

            if mirror {
                let mirror_ident = Ident::new(&format!("mirror_{}", dim_i), Span::call_site());
                mirror_idents.push(quote!{#mirror_ident: bool});
            }
        }

        let mirror_idents2 = mirror_idents.clone();

        let ispub_token = if instance_attribs_hash.contains("pub") {
            quote!{pub}
        } else {
            quote!{}
        };

        let encode_tokens = if !is_abs {
            quote!{
                impl #input_ident {
                    #ispub_token fn #encode_fn_ident<T>(&self,
                        fuses: &mut T, start_coord: (#(#usize_idents),*), #(#mirror_idents),*)
                        where T: ::std::ops::IndexMut<(#(#usize_idents2),*), Output=bool> + ?Sized
                    {
                        #encode_field_tokens
                    }
                }
            }
        } else {
            quote!{
                impl #input_ident {
                    #ispub_token fn #encode_fn_ident<T>(&self, fuses: &mut T)
                        where T: ::std::ops::IndexMut<(#(#usize_idents2),*), Output=bool> + ?Sized
                    {
                        #encode_field_tokens
                    }
                }
            }
        };

        all_tokens.append_all(encode_tokens);

        let decode_output_tokens = if errtype.is_some() {
            let errtype = errtype.as_ref().unwrap();
            quote! {
                Result<Self, #errtype>
            }
        } else {
            quote! {Self}
        };

        let decode_return_tokens = match overall_type {
            BitTwiddlerObjType::Enum => {quote!{self_}},
            BitTwiddlerObjType::Named => {
                if errtype.is_some() {
                    quote!{
                        Ok(Self {
                            #(#decode_field_ids),*
                        })
                    }
                } else {
                    quote!{
                        Self {
                            #(#decode_field_ids),*
                        }
                    }
                }
            },
            BitTwiddlerObjType::Unnamed => {
                if errtype.is_some() {
                    quote!{
                        Ok(#input_ident (
                            #(#decode_field_ids),*
                        ))
                    }
                } else {
                    quote!{
                        #input_ident (
                            #(#decode_field_ids),*
                        )
                    }
                }
            }
        };

        let decode_tokens = if !is_abs {
            quote!{
                impl #input_ident {
                    #ispub_token fn #decode_fn_ident<T>(
                        fuses: &T, start_coord: (#(#usize_idents3),*), #(#mirror_idents2),*)
                        -> #decode_output_tokens
                        where T: ::std::ops::Index<(#(#usize_idents4),*), Output=bool> + ?Sized
                    {
                        #decode_field_tokens

                        #decode_return_tokens
                    }
                }
            }
        } else {
            quote!{
                impl #input_ident {
                    #ispub_token fn #decode_fn_ident<T>(fuses: &T) -> #decode_output_tokens
                        where T: ::std::ops::Index<(#(#usize_idents4),*), Output=bool> + ?Sized
                    {
                        #decode_field_tokens

                        #decode_return_tokens
                    }
                }
            }
        };

        all_tokens.append_all(decode_tokens);
    }

    all_tokens.into()
}
<commit_msg>bittwiddler: Remove old bittwiddler implementation<commit_after>extern crate proc_macro;
use proc_macro::TokenStream;
use proc_macro_error::*;

mod args;

mod bitpattern;

#[proc_macro_error]
#[proc_macro_attribute]
pub fn bitpattern(args: TokenStream, input: TokenStream) -> TokenStream {
    bitpattern::bitpattern(args, input)
}

mod bitfragment;

#[proc_macro_error]
#[proc_macro_attribute]
pub fn bitfragment(args: TokenStream, input: TokenStream) -> TokenStream {
    bitfragment::bitfragment(args, input)
}
<|endoftext|>


<commit_before>use cocoa::base::id;
use cocoa::foundation::NSUInteger
use objc::runtime::BOOL;
use MTLDataType;

pub trait MTLVertexAttribute {
	/// The name of the attribute. (read-only)
	unsafe fn name(self) -> id;

	/// The index of the attribute, as declared in Metal shader source code.
	/// (read-only)
	unsafe fn attributeIndex(self) -> id;

	/// The data type for the attribute, as declared in Metal shader source code.
	/// (read-only)
	unsafe fn attributeType(self) -> MTLDataType;

	/// A Boolean value that indicates whether this vertex attribute is active.
	/// (read-only)
	///
	/// #Discussion
	///
	/// If NO, this attribute is inactive and can be ignored.
	unsafe fn active(self) -> BOOL;
}

impl MTLVertexAttribute for id {
	unsafe fn name(self) -> id {
		msg_send![self, name]
	}
	unsafe fn attributeIndex(self) -> id {
		msg_send![self, attributeIndex]
	}
	unsafe fn attributeType(self) -> MTLDataType {
		msg_send![self, attributeType]
	}
	unsafe fn active(self) -> BOOL {
		msg_send![self, active]
	}
}
<commit_msg>rustfmt<commit_after>use cocoa::base::id;
use cocoa::foundation::NSUInteger;
use objc::runtime::BOOL;
use MTLDataType;

pub trait MTLVertexAttribute {
    /// The name of the attribute. (read-only)
    unsafe fn name(self) -> id;

    /// The index of the attribute, as declared in Metal shader source code.
    /// (read-only)
    unsafe fn attributeIndex(self) -> id;

    /// The data type for the attribute, as declared in Metal shader source code.
    /// (read-only)
    unsafe fn attributeType(self) -> MTLDataType;

    /// A Boolean value that indicates whether this vertex attribute is active.
    /// (read-only)
    ///
    /// #Discussion
    ///
    /// If NO, this attribute is inactive and can be ignored.
    unsafe fn active(self) -> BOOL;
}

impl MTLVertexAttribute for id {
    unsafe fn name(self) -> id {
        msg_send![self, name]
    }
    unsafe fn attributeIndex(self) -> id {
        msg_send![self, attributeIndex]
    }
    unsafe fn attributeType(self) -> MTLDataType {
        msg_send![self, attributeType]
    }
    unsafe fn active(self) -> BOOL {
        msg_send![self, active]
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![deny(unsafe_code)]

extern crate malloc_size_of;
#[macro_use] extern crate malloc_size_of_derive;
extern crate num_traits;
#[macro_use] extern crate serde;

use std::cmp::{self, max, min};
use std::fmt;
use std::ops;

pub trait Int:
    Copy
    + ops::Add<Self, Output=Self>
    + ops::Sub<Self, Output=Self>
    + cmp::Ord
{
    fn zero() -> Self;
    fn one() -> Self;
    fn max_value() -> Self;
    fn from_usize(n: usize) -> Option<Self>;
    fn to_usize(self) -> usize;
}
impl Int for isize {
    #[inline]
    fn zero() -> isize { 0 }
    #[inline]
    fn one() -> isize { 1 }
    #[inline]
    fn max_value() -> isize { ::std::isize::MAX }
    #[inline]
    fn from_usize(n: usize) -> Option<isize> { num_traits::NumCast::from(n) }
    #[inline]
    fn to_usize(self) -> usize { num_traits::NumCast::from(self).unwrap() }
}
impl Int for usize {
    #[inline]
    fn zero() -> usize { 0 }
    #[inline]
    fn one() -> usize { 1 }
    #[inline]
    fn max_value() -> usize { ::std::usize::MAX }
    #[inline]
    fn from_usize(n: usize) -> Option<usize> { Some(n) }
    #[inline]
    fn to_usize(self) -> usize { self }
}

/// An index type to be used by a `Range`
pub trait RangeIndex: Int + fmt::Debug {
    type Index;
    fn new(x: Self::Index) -> Self;
    fn get(self) -> Self::Index;
}

impl RangeIndex for isize {
    type Index = isize;
    #[inline]
    fn new(x: isize) -> isize { x }

    #[inline]
    fn get(self) -> isize { self }
}

impl RangeIndex for usize {
    type Index = usize;
    #[inline]
    fn new(x: usize) -> usize { x }

    #[inline]
    fn get(self) -> usize { self }
}

/// Implements a range index type with operator overloads
#[macro_export]
macro_rules! int_range_index {
    ($(#[$attr:meta])* struct $Self_:ident($T:ty)) => (
        #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
        $(#[$attr])*
        pub struct $Self_(pub $T);

        impl $Self_ {
            #[inline]
            pub fn to_usize(self) -> usize {
                self.get() as usize
            }
        }

        impl $crate::RangeIndex for $Self_ {
            type Index = $T;
            #[inline]
            fn new(x: $T) -> $Self_ {
                $Self_(x)
            }

            #[inline]
            fn get(self) -> $T {
                match self { $Self_(x) => x }
            }
        }

        impl $crate::Int for $Self_ {
            #[inline]
            fn zero() -> $Self_ { $Self_($crate::Int::zero()) }
            #[inline]
            fn one() -> $Self_ { $Self_($crate::Int::one()) }
            #[inline]
            fn max_value() -> $Self_ { $Self_($crate::Int::max_value()) }
            #[inline]
            fn from_usize(n: usize) -> Option<$Self_> { $crate::Int::from_usize(n).map($Self_) }
            #[inline]
            fn to_usize(self) -> usize { self.to_usize() }
        }

        impl ::std::ops::Add<$Self_> for $Self_ {
            type Output = $Self_;

            #[inline]
            fn add(self, other: $Self_) -> $Self_ {
                $Self_(self.get() + other.get())
            }
        }

        impl ::std::ops::Sub<$Self_> for $Self_ {
            type Output = $Self_;

            #[inline]
            fn sub(self, other: $Self_) -> $Self_ {
                $Self_(self.get() - other.get())
            }
        }

        impl ::std::ops::Neg for $Self_ {
            type Output = $Self_;

            #[inline]
            fn neg(self) -> $Self_ {
                $Self_(-self.get())
            }
        }
    )
}

/// A range of indices
#[derive(Clone, Copy, Deserialize, MallocSizeOf, Serialize)]
pub struct Range<I> {
    begin: I,
    length: I,
}

impl<I: RangeIndex> fmt::Debug for Range<I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?} .. {:?})", self.begin(), self.end())
    }
}

/// An iterator over each index in a range
pub struct EachIndex<I: RangeIndex> {
    start: I,
    stop: I,
}

pub fn each_index<I: RangeIndex>(start: I, stop: I) -> EachIndex<I> {
    EachIndex { start, stop }
}

impl<I: RangeIndex> Iterator for EachIndex<I> {
    type Item = I;

    #[inline]
    fn next(&mut self) -> Option<I> {
        if self.start < self.stop {
            let next = self.start;
            self.start = next + I::one();
            Some(next)
        } else {
            None
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.start < self.stop {
            let len = (self.stop - self.start).to_usize();
            (len, Some(len))
        } else {
            (0, Some(0))
        }
    }
}

impl<I: RangeIndex> Range<I> {
    /// Create a new range from beginning and length offsets. This could be
    /// denoted as `[begin, begin + length)`.
    ///
    /// ~~~ignore
    ///    |-- begin ->|-- length ->|
    ///    |           |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn new(begin: I, length: I) -> Range<I> {
        Range { begin: begin, length: length }
    }

    #[inline]
    pub fn empty() -> Range<I> {
        Range::new(Int::zero(), Int::zero())
    }

    /// The index offset to the beginning of the range.
    ///
    /// ~~~ignore
    ///    |-- begin ->|
    ///    |           |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn begin(&self) -> I { self.begin  }

    /// The index offset from the beginning to the end of the range.
    ///
    /// ~~~ignore
    ///                |-- length ->|
    ///                |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn length(&self) -> I { self.length }

    /// The index offset to the end of the range.
    ///
    /// ~~~ignore
    ///    |--------- end --------->|
    ///    |                        |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn end(&self) -> I { self.begin + self.length }

    /// `true` if the index is between the beginning and the end of the range.
    ///
    /// ~~~ignore
    ///        false        true      false
    ///          |           |          |
    /// <- o - - + - - +=====+======+ - + - ->
    /// ~~~
    #[inline]
    pub fn contains(&self, i: I) -> bool {
        i >= self.begin() && i < self.end()
    }

    /// `true` if the offset from the beginning to the end of the range is zero.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.length() == Int::zero()
    }

    /// Shift the entire range by the supplied index delta.
    ///
    /// ~~~ignore
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - +============+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn shift_by(&mut self, delta: I) {
        self.begin = self.begin + delta;
    }

    /// Extend the end of the range by the supplied index delta.
    ///
    /// ~~~ignore
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_by(&mut self, delta: I) {
        self.length = self.length + delta;
    }

    /// Move the end of the range to the target index.
    ///
    /// ~~~ignore
    ///                               target
    ///                                 |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_to(&mut self, target: I) {
        self.length = target - self.begin;
    }

    /// Adjust the beginning offset and the length by the supplied deltas.
    #[inline]
    pub fn adjust_by(&mut self, begin_delta: I, length_delta: I) {
        self.begin = self.begin + begin_delta;
        self.length = self.length + length_delta;
    }

    /// Set the begin and length values.
    #[inline]
    pub fn reset(&mut self, begin: I, length: I) {
        self.begin = begin;
        self.length = length;
    }

    #[inline]
    pub fn intersect(&self, other: &Range<I>) -> Range<I> {
        let begin = max(self.begin(), other.begin());
        let end = min(self.end(), other.end());

        if end < begin {
            Range::empty()
        } else {
            Range::new(begin, end - begin)
        }
    }
}

/// Methods for `Range`s with indices based on integer values
impl<I: RangeIndex> Range<I> {
    /// Returns an iterater that increments over `[begin, end)`.
    #[inline]
    pub fn each_index(&self) -> EachIndex<I> {
        each_index(self.begin(), self.end())
    }
}
<commit_msg>format components/range using rustfmt<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![deny(unsafe_code)]

extern crate malloc_size_of;
#[macro_use]
extern crate malloc_size_of_derive;
extern crate num_traits;
#[macro_use]
extern crate serde;

use std::cmp::{self, max, min};
use std::fmt;
use std::ops;

pub trait Int:
    Copy + ops::Add<Self, Output = Self> + ops::Sub<Self, Output = Self> + cmp::Ord
{
    fn zero() -> Self;
    fn one() -> Self;
    fn max_value() -> Self;
    fn from_usize(n: usize) -> Option<Self>;
    fn to_usize(self) -> usize;
}
impl Int for isize {
    #[inline]
    fn zero() -> isize {
        0
    }
    #[inline]
    fn one() -> isize {
        1
    }
    #[inline]
    fn max_value() -> isize {
        ::std::isize::MAX
    }
    #[inline]
    fn from_usize(n: usize) -> Option<isize> {
        num_traits::NumCast::from(n)
    }
    #[inline]
    fn to_usize(self) -> usize {
        num_traits::NumCast::from(self).unwrap()
    }
}
impl Int for usize {
    #[inline]
    fn zero() -> usize {
        0
    }
    #[inline]
    fn one() -> usize {
        1
    }
    #[inline]
    fn max_value() -> usize {
        ::std::usize::MAX
    }
    #[inline]
    fn from_usize(n: usize) -> Option<usize> {
        Some(n)
    }
    #[inline]
    fn to_usize(self) -> usize {
        self
    }
}

/// An index type to be used by a `Range`
pub trait RangeIndex: Int + fmt::Debug {
    type Index;
    fn new(x: Self::Index) -> Self;
    fn get(self) -> Self::Index;
}

impl RangeIndex for isize {
    type Index = isize;
    #[inline]
    fn new(x: isize) -> isize {
        x
    }

    #[inline]
    fn get(self) -> isize {
        self
    }
}

impl RangeIndex for usize {
    type Index = usize;
    #[inline]
    fn new(x: usize) -> usize {
        x
    }

    #[inline]
    fn get(self) -> usize {
        self
    }
}

/// Implements a range index type with operator overloads
#[macro_export]
macro_rules! int_range_index {
    ($(#[$attr:meta])* struct $Self_:ident($T:ty)) => (
        #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
        $(#[$attr])*
        pub struct $Self_(pub $T);

        impl $Self_ {
            #[inline]
            pub fn to_usize(self) -> usize {
                self.get() as usize
            }
        }

        impl $crate::RangeIndex for $Self_ {
            type Index = $T;
            #[inline]
            fn new(x: $T) -> $Self_ {
                $Self_(x)
            }

            #[inline]
            fn get(self) -> $T {
                match self { $Self_(x) => x }
            }
        }

        impl $crate::Int for $Self_ {
            #[inline]
            fn zero() -> $Self_ { $Self_($crate::Int::zero()) }
            #[inline]
            fn one() -> $Self_ { $Self_($crate::Int::one()) }
            #[inline]
            fn max_value() -> $Self_ { $Self_($crate::Int::max_value()) }
            #[inline]
            fn from_usize(n: usize) -> Option<$Self_> { $crate::Int::from_usize(n).map($Self_) }
            #[inline]
            fn to_usize(self) -> usize { self.to_usize() }
        }

        impl ::std::ops::Add<$Self_> for $Self_ {
            type Output = $Self_;

            #[inline]
            fn add(self, other: $Self_) -> $Self_ {
                $Self_(self.get() + other.get())
            }
        }

        impl ::std::ops::Sub<$Self_> for $Self_ {
            type Output = $Self_;

            #[inline]
            fn sub(self, other: $Self_) -> $Self_ {
                $Self_(self.get() - other.get())
            }
        }

        impl ::std::ops::Neg for $Self_ {
            type Output = $Self_;

            #[inline]
            fn neg(self) -> $Self_ {
                $Self_(-self.get())
            }
        }
    )
}

/// A range of indices
#[derive(Clone, Copy, Deserialize, MallocSizeOf, Serialize)]
pub struct Range<I> {
    begin: I,
    length: I,
}

impl<I: RangeIndex> fmt::Debug for Range<I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{:?} .. {:?})", self.begin(), self.end())
    }
}

/// An iterator over each index in a range
pub struct EachIndex<I: RangeIndex> {
    start: I,
    stop: I,
}

pub fn each_index<I: RangeIndex>(start: I, stop: I) -> EachIndex<I> {
    EachIndex { start, stop }
}

impl<I: RangeIndex> Iterator for EachIndex<I> {
    type Item = I;

    #[inline]
    fn next(&mut self) -> Option<I> {
        if self.start < self.stop {
            let next = self.start;
            self.start = next + I::one();
            Some(next)
        } else {
            None
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.start < self.stop {
            let len = (self.stop - self.start).to_usize();
            (len, Some(len))
        } else {
            (0, Some(0))
        }
    }
}

impl<I: RangeIndex> Range<I> {
    /// Create a new range from beginning and length offsets. This could be
    /// denoted as `[begin, begin + length)`.
    ///
    /// ~~~ignore
    ///    |-- begin ->|-- length ->|
    ///    |           |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn new(begin: I, length: I) -> Range<I> {
        Range {
            begin: begin,
            length: length,
        }
    }

    #[inline]
    pub fn empty() -> Range<I> {
        Range::new(Int::zero(), Int::zero())
    }

    /// The index offset to the beginning of the range.
    ///
    /// ~~~ignore
    ///    |-- begin ->|
    ///    |           |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn begin(&self) -> I {
        self.begin
    }

    /// The index offset from the beginning to the end of the range.
    ///
    /// ~~~ignore
    ///                |-- length ->|
    ///                |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn length(&self) -> I {
        self.length
    }

    /// The index offset to the end of the range.
    ///
    /// ~~~ignore
    ///    |--------- end --------->|
    ///    |                        |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn end(&self) -> I {
        self.begin + self.length
    }

    /// `true` if the index is between the beginning and the end of the range.
    ///
    /// ~~~ignore
    ///        false        true      false
    ///          |           |          |
    /// <- o - - + - - +=====+======+ - + - ->
    /// ~~~
    #[inline]
    pub fn contains(&self, i: I) -> bool {
        i >= self.begin() && i < self.end()
    }

    /// `true` if the offset from the beginning to the end of the range is zero.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.length() == Int::zero()
    }

    /// Shift the entire range by the supplied index delta.
    ///
    /// ~~~ignore
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - +============+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn shift_by(&mut self, delta: I) {
        self.begin = self.begin + delta;
    }

    /// Extend the end of the range by the supplied index delta.
    ///
    /// ~~~ignore
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_by(&mut self, delta: I) {
        self.length = self.length + delta;
    }

    /// Move the end of the range to the target index.
    ///
    /// ~~~ignore
    ///                               target
    ///                                 |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_to(&mut self, target: I) {
        self.length = target - self.begin;
    }

    /// Adjust the beginning offset and the length by the supplied deltas.
    #[inline]
    pub fn adjust_by(&mut self, begin_delta: I, length_delta: I) {
        self.begin = self.begin + begin_delta;
        self.length = self.length + length_delta;
    }

    /// Set the begin and length values.
    #[inline]
    pub fn reset(&mut self, begin: I, length: I) {
        self.begin = begin;
        self.length = length;
    }

    #[inline]
    pub fn intersect(&self, other: &Range<I>) -> Range<I> {
        let begin = max(self.begin(), other.begin());
        let end = min(self.end(), other.end());

        if end < begin {
            Range::empty()
        } else {
            Range::new(begin, end - begin)
        }
    }
}

/// Methods for `Range`s with indices based on integer values
impl<I: RangeIndex> Range<I> {
    /// Returns an iterater that increments over `[begin, end)`.
    #[inline]
    pub fn each_index(&self) -> EachIndex<I> {
        each_index(self.begin(), self.end())
    }
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/maximum-xor-after-operations/
pub fn maximum_xor(nums: Vec<i32>) -> i32 {
    todo!()
}

fn main() {
    println!("{}", maximum_xor(vec![3, 2, 4, 6])); // 7
    println!("{}", maximum_xor(vec![1, 2, 3, 9, 2])); // 11
}
<commit_msg>Update problem 2317<commit_after>// https://leetcode.com/problems/maximum-xor-after-operations/
pub fn maximum_xor(nums: Vec<i32>) -> i32 {
    todo!()
}

fn main() {
    println!("{}", maximum_xor(vec![3, 2, 4, 6])); // 7
    println!("{}", maximum_xor(vec![1, 2, 3, 9, 2])); // 11
    println!("{}", maximum_xor(vec![1, 2, 3, 9])); // 11
    println!("{}", maximum_xor(vec![1, 2, 3, 9, 9, 9])); // 11
}
<|endoftext|>


<commit_before>use std::{
    fs::File, io, os::unix::io::{AsRawFd, FromRawFd, RawFd},
};
use sys;

/// Use dup2 to replace `old` with `new` using `old`s file descriptor ID
pub(crate) fn redir(old: RawFd, new: RawFd) {
    if let Err(e) = sys::dup2(old, new) {
        eprintln!("ion: could not duplicate {} to {}: {}", old, new, e);
    }
}

/// Duplicates STDIN, STDOUT, and STDERR; in that order; and returns them as `File`s.
/// Why, you ask? A simple safety mechanism to ensure that the duplicated FDs are closed
/// when dropped.
pub(crate) fn duplicate_streams() -> io::Result<(File, File, File)> {
    // Duplicates STDIN and converts it into a `File`.
    sys::dup(sys::STDIN_FILENO).map(|fd| unsafe { File::from_raw_fd(fd) })
        // Do the same for stdout, and then meld the result with stdin
        .and_then(|stdin| sys::dup(sys::STDOUT_FILENO)
            .map(|fd| unsafe { File::from_raw_fd(fd) })
            .map(|stdout| (stdin, stdout))
        )
        // And then meld stderr alongside stdin and stdout
        .and_then(|(stdin, stdout)| sys::dup(sys::STDERR_FILENO)
            .map(|fd| unsafe { File::from_raw_fd(fd) })
            .map(|stderr| (stdin, stdout, stderr))
        )
}

pub(crate) fn redirect_streams(inp: File, out: File, err: File) {
    redir(inp.as_raw_fd(), sys::STDIN_FILENO);
    redir(out.as_raw_fd(), sys::STDOUT_FILENO);
    redir(err.as_raw_fd(), sys::STDERR_FILENO);
}
<commit_msg>Fix background jobs that don't request TTY access<commit_after>use std::{
    fs::File, io, os::unix::io::{AsRawFd, FromRawFd, RawFd},
};
use sys;

/// Use dup2 to replace `old` with `new` using `old`s file descriptor ID
pub(crate) fn redir(old: RawFd, new: RawFd) {
    if let Err(e) = sys::dup2(old, new) {
        eprintln!("ion: could not duplicate {} to {}: {}", old, new, e);
    }
}

/// Duplicates STDIN, STDOUT, and STDERR; in that order; and returns them as `File`s.
/// Why, you ask? A simple safety mechanism to ensure that the duplicated FDs are closed
/// when dropped.
pub(crate) fn duplicate_streams() -> io::Result<(Option<File>, File, File)> {
    // STDIN may have been closed for a background shell, so it is ok if it cannot be duplicated.
    let stdin = sys::dup(sys::STDIN_FILENO).ok().map(|fd| unsafe { File::from_raw_fd(fd) });

    sys::dup(sys::STDOUT_FILENO)
        .map(|fd| unsafe { File::from_raw_fd(fd) })
        .map(|stdout| (stdin, stdout))
        // And then meld stderr alongside stdin and stdout
        .and_then(|(stdin, stdout)| sys::dup(sys::STDERR_FILENO)
            .map(|fd| unsafe { File::from_raw_fd(fd) })
            .map(|stderr| (stdin, stdout, stderr))
        )
}

pub(crate) fn redirect_streams(inp: Option<File>, out: File, err: File) {
    if let Some(inp) = inp {
        redir(inp.as_raw_fd(), sys::STDIN_FILENO);
    }
    redir(out.as_raw_fd(), sys::STDOUT_FILENO);
    redir(err.as_raw_fd(), sys::STDERR_FILENO);
}
<|endoftext|>


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

use std::fmt;
use std::iter::FromIterator;
use std::slice;

// Note 1: It is not clear whether the flexibility of providing both
// the `Growable` and `FixedLen` variants is sufficiently useful.
// Consider restricting to just a two variant enum.

// Note 2: Once Dynamically Sized Types (DST) lands, it might be
// reasonable to replace this with something like `enum MaybeOwned<'a,
// Sized? U>{ Owned(Box<U>), Borrowed(&'a U) }`; and then `U` could be
// instantiated with `[T]` or `str`, etc.  Of course, that would imply
// removing the `Growable` variant, which relates to note 1 above.
// Alternatively, we might add `MaybeOwned` for the general case but
// keep some form of `MaybeOwnedVector` to avoid unnecessary copying
// of the contents of `Vec<T>`, since we anticipate that to be a
// frequent way to dynamically construct a vector.

/// MaybeOwnedVector<'a,T> abstracts over `Vec<T>`, `&'a [T]`.
///
/// Some clients will have a pre-allocated vector ready to hand off in
/// a slice; others will want to create the set on the fly and hand
/// off ownership, via `Growable`.
pub enum MaybeOwnedVector<'a,T> {
    Growable(Vec<T>),
    Borrowed(&'a [T]),
}

/// Trait for moving into a `MaybeOwnedVector`
pub trait IntoMaybeOwnedVector<'a,T> {
    /// Moves self into a `MaybeOwnedVector`
    fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T>;
}

impl<'a,T> IntoMaybeOwnedVector<'a,T> for Vec<T> {
    #[inline]
    fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Growable(self) }
}

impl<'a,T> IntoMaybeOwnedVector<'a,T> for &'a [T] {
    #[inline]
    fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Borrowed(self) }
}

impl<'a,T> MaybeOwnedVector<'a,T> {
    pub fn iter(&'a self) -> slice::Items<'a,T> {
        match self {
            &Growable(ref v) => v.iter(),
            &Borrowed(ref v) => v.iter(),
        }
    }
}

// The `Vector` trait is provided in the prelude and is implemented on
// both `&'a [T]` and `Vec<T>`, so it makes sense to try to support it
// seamlessly.  The other vector related traits from the prelude do
// not appear to be implemented on both `&'a [T]` and `Vec<T>`.  (It
// is possible that this is an oversight in some cases.)
//
// In any case, with `Vector` in place, the client can just use
// `as_slice` if they prefer that over `match`.

impl<'b,T> slice::Vector<T> for MaybeOwnedVector<'b,T> {
    fn as_slice<'a>(&'a self) -> &'a [T] {
        match self {
            &Growable(ref v) => v.as_slice(),
            &Borrowed(ref v) => v.as_slice(),
        }
    }
}

impl<'a,T> FromIterator<T> for MaybeOwnedVector<'a,T> {
    fn from_iter<I:Iterator<T>>(iterator: I) -> MaybeOwnedVector<T> {
        // If we are building from scratch, might as well build the
        // most flexible variant.
        Growable(FromIterator::from_iter(iterator))
    }
}

impl<'a,T:fmt::Show> fmt::Show for MaybeOwnedVector<'a,T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

impl<'a,T:Clone> CloneableVector<T> for MaybeOwnedVector<'a,T> {
    /// Returns a copy of `self`.
    fn to_owned(&self) -> Vec<T> {
        self.as_slice().to_owned()
    }

    /// Convert `self` into an owned slice, not making a copy if possible.
    fn into_owned(self) -> Vec<T> {
        match self {
            Growable(v) => v.as_slice().to_owned(),
            Borrowed(v) => v.to_owned(),
        }
    }
}

impl<'a,T:Clone> MaybeOwnedVector<'a,T> {
    /// Convert `self` into a growable `Vec`, not making a copy if possible.
    pub fn into_vec(self) -> Vec<T> {
        match self {
            Growable(v) => v,
            Borrowed(v) => Vec::from_slice(v),
        }
    }
}
<commit_msg>auto merge of #15241 : arjantop/rust/maybeownedvector-improvements, r=alexcrichton<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::collections::Collection;
use std::default::Default;
use std::fmt;
use std::iter::FromIterator;
use std::path::BytesContainer;
use std::slice;

// Note 1: It is not clear whether the flexibility of providing both
// the `Growable` and `FixedLen` variants is sufficiently useful.
// Consider restricting to just a two variant enum.

// Note 2: Once Dynamically Sized Types (DST) lands, it might be
// reasonable to replace this with something like `enum MaybeOwned<'a,
// Sized? U>{ Owned(Box<U>), Borrowed(&'a U) }`; and then `U` could be
// instantiated with `[T]` or `str`, etc.  Of course, that would imply
// removing the `Growable` variant, which relates to note 1 above.
// Alternatively, we might add `MaybeOwned` for the general case but
// keep some form of `MaybeOwnedVector` to avoid unnecessary copying
// of the contents of `Vec<T>`, since we anticipate that to be a
// frequent way to dynamically construct a vector.

/// MaybeOwnedVector<'a,T> abstracts over `Vec<T>`, `&'a [T]`.
///
/// Some clients will have a pre-allocated vector ready to hand off in
/// a slice; others will want to create the set on the fly and hand
/// off ownership, via `Growable`.
pub enum MaybeOwnedVector<'a,T> {
    Growable(Vec<T>),
    Borrowed(&'a [T]),
}

/// Trait for moving into a `MaybeOwnedVector`
pub trait IntoMaybeOwnedVector<'a,T> {
    /// Moves self into a `MaybeOwnedVector`
    fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T>;
}

impl<'a,T> IntoMaybeOwnedVector<'a,T> for Vec<T> {
    #[inline]
    fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Growable(self) }
}

impl<'a,T> IntoMaybeOwnedVector<'a,T> for &'a [T] {
    #[inline]
    fn into_maybe_owned(self) -> MaybeOwnedVector<'a,T> { Borrowed(self) }
}

impl<'a,T> MaybeOwnedVector<'a,T> {
    pub fn iter(&'a self) -> slice::Items<'a,T> {
        match self {
            &Growable(ref v) => v.iter(),
            &Borrowed(ref v) => v.iter(),
        }
    }
}

impl<'a, T: PartialEq> PartialEq for MaybeOwnedVector<'a, T> {
    fn eq(&self, other: &MaybeOwnedVector<T>) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl<'a, T: Eq> Eq for MaybeOwnedVector<'a, T> {}

impl<'a, T: PartialOrd> PartialOrd for MaybeOwnedVector<'a, T> {
    fn lt(&self, other: &MaybeOwnedVector<T>) -> bool {
        self.as_slice().lt(&other.as_slice())
    }
}

impl<'a, T: Ord> Ord for MaybeOwnedVector<'a, T> {
    fn cmp(&self, other: &MaybeOwnedVector<T>) -> Ordering {
        self.as_slice().cmp(&other.as_slice())
    }
}

impl<'a, T: PartialEq, V: Vector<T>> Equiv<V> for MaybeOwnedVector<'a, T> {
    fn equiv(&self, other: &V) -> bool {
        self.as_slice() == other.as_slice()
    }
}

// The `Vector` trait is provided in the prelude and is implemented on
// both `&'a [T]` and `Vec<T>`, so it makes sense to try to support it
// seamlessly.  The other vector related traits from the prelude do
// not appear to be implemented on both `&'a [T]` and `Vec<T>`.  (It
// is possible that this is an oversight in some cases.)
//
// In any case, with `Vector` in place, the client can just use
// `as_slice` if they prefer that over `match`.

impl<'b,T> slice::Vector<T> for MaybeOwnedVector<'b,T> {
    fn as_slice<'a>(&'a self) -> &'a [T] {
        match self {
            &Growable(ref v) => v.as_slice(),
            &Borrowed(ref v) => v.as_slice(),
        }
    }
}

impl<'a,T> FromIterator<T> for MaybeOwnedVector<'a,T> {
    fn from_iter<I:Iterator<T>>(iterator: I) -> MaybeOwnedVector<T> {
        // If we are building from scratch, might as well build the
        // most flexible variant.
        Growable(FromIterator::from_iter(iterator))
    }
}

impl<'a,T:fmt::Show> fmt::Show for MaybeOwnedVector<'a,T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

impl<'a,T:Clone> CloneableVector<T> for MaybeOwnedVector<'a,T> {
    /// Returns a copy of `self`.
    fn to_owned(&self) -> Vec<T> {
        self.as_slice().to_owned()
    }

    /// Convert `self` into an owned slice, not making a copy if possible.
    fn into_owned(self) -> Vec<T> {
        match self {
            Growable(v) => v.as_slice().to_owned(),
            Borrowed(v) => v.to_owned(),
        }
    }
}

impl<'a, T: Clone> Clone for MaybeOwnedVector<'a, T> {
    fn clone(&self) -> MaybeOwnedVector<'a, T> {
        match *self {
            Growable(ref v) => Growable(v.to_owned()),
            Borrowed(v) => Borrowed(v)
        }
    }
}

impl<'a, T> Default for MaybeOwnedVector<'a, T> {
    fn default() -> MaybeOwnedVector<'a, T> {
        Growable(Vec::new())
    }
}

impl<'a, T> Collection for MaybeOwnedVector<'a, T> {
    fn len(&self) -> uint {
        self.as_slice().len()
    }
}

impl<'a> BytesContainer for MaybeOwnedVector<'a, u8> {
    fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
        self.as_slice()
    }
}

impl<'a,T:Clone> MaybeOwnedVector<'a,T> {
    /// Convert `self` into a growable `Vec`, not making a copy if possible.
    pub fn into_vec(self) -> Vec<T> {
        match self {
            Growable(v) => v,
            Borrowed(v) => Vec::from_slice(v),
        }
    }
}
<|endoftext|>