<commit_before>//! Endpoints for getting and synchronizing events.

/// [GET /_matrix/client/r0/rooms/{roomId}/state](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-state)
pub mod get_state_events {
    use ruma_api_macros::ruma_api;
    use ruma_events::collections::only;
    use ruma_identifiers::RoomId;

    ruma_api! {
        metadata {
            description: "Get state events for a room.",
            method: Method::Get,
            name: "get_state_events",
            path: "/_matrix/client/r0/rooms/:room_id/state",
            rate_limited: false,
            requires_authentication: true,
        }

        request {
            /// The room to look up the state for.
            #[ruma_api(path)]
            pub room_id: RoomId,
        }

        response {
            /// If the user is a member of the room this will be the current state of the room as a
            /// list of events. If the user has left the room then this will be the state of the
            /// room when they left as a list of events.
            #[ruma_api(body)]
            pub room_state: Vec<only::StateEvent>,
        }
    }
}

/// [GET /_matrix/client/r0/rooms/{roomId}/state/{eventType}](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-state-eventtype)
pub mod get_state_events_for_empty_key {
    use ruma_api_macros::ruma_api;
    use ruma_events::EventType;
    use ruma_identifiers::RoomId;

    ruma_api! {
        metadata {
            description: "Get state events of a given type associated with the empty key.",
            method: Method::Get,
            name: "get_state_events_for_empty_key",
            path: "/_matrix/client/r0/rooms/:room_id/state/:event_type",
            rate_limited: false,
            requires_authentication: true,
        }

        request {
            /// The room to look up the state for.
            #[ruma_api(path)]
            pub room_id: RoomId,
            /// The type of state to look up.
            #[ruma_api(path)]
            pub event_type: EventType,
        }

        response {
            /// The content of the state event.
            #[ruma_api(body)]
            pub content: ::serde_json::Value,
        }
    }
}

/// [GET /_matrix/client/r0/rooms/{roomId}/state/{eventType}/{stateKey}](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-state-eventtype-state-key)
pub mod get_state_events_for_key {
    use ruma_api_macros::ruma_api;
    use ruma_identifiers::RoomId;

    ruma_api! {
        metadata {
            description: "Get state events associated with a given key.",
            method: Method::Get,
            name: "get_state_events_for_key",
            path: "/_matrix/client/r0/rooms/:room_id/state/:event_type/:state_key",
            rate_limited: false,
            requires_authentication: true,
        }

        request {
            /// The room to look up the state for.
            #[ruma_api(path)]
            pub room_id: RoomId,
            /// The type of state to look up.
            #[ruma_api(path)]
            pub event_type: String,
            /// The key of the state to look up.
            #[ruma_api(path)]
            pub state_key: String,
        }

        response {
            /// The content of the state event.
            #[ruma_api(body)]
            pub content: ::serde_json::Value,
        }
    }
}

/// [GET /_matrix/client/r0/rooms/{roomId}/members](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-members)
pub mod get_member_events {
    use ruma_api_macros::ruma_api;
    use ruma_events::room::member::MemberEvent;
    use ruma_identifiers::RoomId;

    ruma_api! {
        metadata {
            description: "Get membership events for a room.",
            method: Method::Get,
            name: "get_member_events",
            path: "/_matrix/client/r0/rooms/:room_id/members",
            rate_limited: false,
            requires_authentication: false,
            // TODO: not marked as requiring auth in the spec, but
            // will return a 403 error is user is not a member of the
            // room anyway...
        }

        request {
            /// The room to get the member events for.
            #[ruma_api(path)]
            pub room_id: RoomId,
        }

        response {
            /// A list of member events.
            pub chunk: Vec<MemberEvent>
        }
    }
}

/// [GET /_matrix/client/r0/rooms/{roomId}/messages](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-messages)
pub mod get_message_events {
    use ruma_api_macros::ruma_api;
    use ruma_events::collections::only;
    use ruma_identifiers::RoomId;

    ruma_api! {
        metadata {
            description: "Get message events for a room.",
            method: Method::Get,
            name: "get_message_events",
            path: "/_matrix/client/r0/rooms/:room_id/messages",
            rate_limited: false,
            requires_authentication: true,
        }

        request {
            /// The room to get events from.
            #[ruma_api(path)]
            pub room_id: RoomId,
            /// The token to start returning events from.
            ///
            /// This token can be obtained from a
            /// prev_batch token returned for each room by the sync API, or from a start or end token
            /// returned by a previous request to this endpoint.
            pub from: String,
            /// The token to stop returning events at.
            ///
            /// This token can be obtained from a prev_batch
            /// token returned for each room by the sync endpoint, or from a start or end token returned
            /// by a previous request to this endpoint.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub to: Option<String>,
            /// The direction to return events from.
            pub dir: Direction,
            /// The maximum number of events to return.
            ///
            /// Default: 10.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub limit: Option<u64>,
        }

        response {
            /// The token the pagination starts from.
            pub start: String,
            /// A list of room events.
            pub chunk: Vec<only::RoomEvent>,
            /// The token the pagination ends at.
            pub end: String,
        }
    }

    /// The direction to return events from.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub enum Direction {
        /// Return events backwards in time from the requested `from` token.
        #[serde(rename="b")]
        Backward,
        /// Return events forwards in time from the requested `from` token.
        #[serde(rename="f")]
        Forward,
    }
}

/// [GET /_matrix/client/r0/sync](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync)
pub mod sync_events {
    use std::collections::HashMap;

    use ruma_api_macros::ruma_api;
    use ruma_events::collections::{all, only};
    use ruma_identifiers::RoomId;

    use r0::filter::FilterDefinition;

    ruma_api! {
        metadata {
            description: "Get all new events from all rooms since the last sync or a given point of time.",
            method: Method::Get,
            name: "sync",
            path: "/_matrix/client/r0/sync",
            rate_limited: false,
            requires_authentication: true,
        }

        request {
            /// A filter represented either as its full JSON definition or the ID of a saved filter.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub filter: Option<Filter>,
            /// A point in time to continue a sync from.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub since: Option<String>,
            /// Controls whether to include the full state for all rooms the user is a member of.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub full_state: Option<bool>,
            /// Controls whether the client is automatically marked as online by polling this API.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub set_presence: Option<SetPresence>,
            /// The maximum time to poll in milliseconds before returning this request.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub timeout: Option<u64>,
        }

        response {
            /// The batch token to supply in the `since` param of the next `/sync` request.
            pub next_batch: String,
            /// Updates to rooms.
            pub rooms: Rooms,
            /// Updates to the presence status of other users.
            pub presence: Presence,
        }

    }

    /// Whether to set presence or not during sync.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub enum SetPresence {
        /// Do not set the presence of the user calling this API.
        #[serde(rename="offline")]
        Offline,
    }

    /// A filter represented either as its full JSON definition or the ID of a saved filter.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub enum Filter {
        /// A complete filter definition serialized to JSON.
        FilterDefinition(FilterDefinition),
        /// The ID of a filter saved on the server.
        FilterId(String),
    }

    /// Updates to rooms.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct Rooms {
        /// The rooms that the user has left or been banned from.
        pub leave: HashMap<RoomId, LeftRoom>,
        /// The rooms that the user has joined.
        pub join: HashMap<RoomId, JoinedRoom>,
        /// The rooms that the user has been invited to.
        pub invite: HashMap<RoomId, InvitedRoom>,
    }

    /// Historical updates to left rooms.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct LeftRoom {
        /// The timeline of messages and state changes in the room up to the point when the user
        /// left.
        pub timeline: Timeline,
        /// The state updates for the room up to the start of the timeline.
        pub state: State,
    }

    /// Updates to joined rooms.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct JoinedRoom {
        /// Counts of unread notifications for this room.
        pub unread_notifications: UnreadNotificationsCount,
        /// The timeline of messages and state changes in the room.
        pub timeline: Timeline,
        /// Updates to the state, between the time indicated by the `since` parameter, and the start
        /// of the `timeline` (or all state up to the start of the `timeline`, if `since` is not
        /// given, or `full_state` is true).
        pub state: State,
        /// The private data that this user has attached to this room.
        pub account_data: AccountData,
        /// The ephemeral events in the room that aren't recorded in the timeline or state of the
        /// room. e.g. typing.
        pub ephemeral: Ephemeral,
    }

    /// unread notifications count
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct UnreadNotificationsCount {
        /// The number of unread notifications for this room with the highlight flag set.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub highlight_count: Option<u64>,
        /// The total number of unread notifications for this room.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub notification_count: Option<u64>,
    }

    /// Events in the room.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct Timeline {
        /// True if the number of events returned was limited by the `limit` on the filter.
        pub limited: bool,
        /// A token that can be supplied to to the `from` parameter of the
        /// `/rooms/{roomId}/messages` endpoint.
        pub prev_batch: String,
        /// A list of events.
        pub events: Vec<all::RoomEvent>,
    }

    /// State events in the room.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct State {
        /// A list of state events.
        pub events: Vec<only::StateEvent>,
    }

    /// The private data that this user has attached to this room.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct AccountData {
        /// A list of events.
        pub events: Vec<only::Event>,
    }

    /// Ephemeral events not recorded in the timeline or state of the room.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct Ephemeral {
        /// A list of events.
        pub events: Vec<only::Event>,
    }

    /// Updates to the rooms that the user has been invited to.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct InvitedRoom {
        /// The state of a room that the user has been invited to.
        pub invite_state: InviteState,
    }

    /// The state of a room that the user has been invited to.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct InviteState {
        /// A list of state events.
        pub events: Vec<only::StateEvent>,
    }

    /// Updates to the presence status of other users.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct Presence {
        /// A list of events.
        pub events: Vec<only::Event>,
    }
}
<commit_msg>Serialize sync_events::Filter untagged<commit_after>//! Endpoints for getting and synchronizing events.

/// [GET /_matrix/client/r0/rooms/{roomId}/state](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-state)
pub mod get_state_events {
    use ruma_api_macros::ruma_api;
    use ruma_events::collections::only;
    use ruma_identifiers::RoomId;

    ruma_api! {
        metadata {
            description: "Get state events for a room.",
            method: Method::Get,
            name: "get_state_events",
            path: "/_matrix/client/r0/rooms/:room_id/state",
            rate_limited: false,
            requires_authentication: true,
        }

        request {
            /// The room to look up the state for.
            #[ruma_api(path)]
            pub room_id: RoomId,
        }

        response {
            /// If the user is a member of the room this will be the current state of the room as a
            /// list of events. If the user has left the room then this will be the state of the
            /// room when they left as a list of events.
            #[ruma_api(body)]
            pub room_state: Vec<only::StateEvent>,
        }
    }
}

/// [GET /_matrix/client/r0/rooms/{roomId}/state/{eventType}](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-state-eventtype)
pub mod get_state_events_for_empty_key {
    use ruma_api_macros::ruma_api;
    use ruma_events::EventType;
    use ruma_identifiers::RoomId;

    ruma_api! {
        metadata {
            description: "Get state events of a given type associated with the empty key.",
            method: Method::Get,
            name: "get_state_events_for_empty_key",
            path: "/_matrix/client/r0/rooms/:room_id/state/:event_type",
            rate_limited: false,
            requires_authentication: true,
        }

        request {
            /// The room to look up the state for.
            #[ruma_api(path)]
            pub room_id: RoomId,
            /// The type of state to look up.
            #[ruma_api(path)]
            pub event_type: EventType,
        }

        response {
            /// The content of the state event.
            #[ruma_api(body)]
            pub content: ::serde_json::Value,
        }
    }
}

/// [GET /_matrix/client/r0/rooms/{roomId}/state/{eventType}/{stateKey}](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-state-eventtype-state-key)
pub mod get_state_events_for_key {
    use ruma_api_macros::ruma_api;
    use ruma_identifiers::RoomId;

    ruma_api! {
        metadata {
            description: "Get state events associated with a given key.",
            method: Method::Get,
            name: "get_state_events_for_key",
            path: "/_matrix/client/r0/rooms/:room_id/state/:event_type/:state_key",
            rate_limited: false,
            requires_authentication: true,
        }

        request {
            /// The room to look up the state for.
            #[ruma_api(path)]
            pub room_id: RoomId,
            /// The type of state to look up.
            #[ruma_api(path)]
            pub event_type: String,
            /// The key of the state to look up.
            #[ruma_api(path)]
            pub state_key: String,
        }

        response {
            /// The content of the state event.
            #[ruma_api(body)]
            pub content: ::serde_json::Value,
        }
    }
}

/// [GET /_matrix/client/r0/rooms/{roomId}/members](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-members)
pub mod get_member_events {
    use ruma_api_macros::ruma_api;
    use ruma_events::room::member::MemberEvent;
    use ruma_identifiers::RoomId;

    ruma_api! {
        metadata {
            description: "Get membership events for a room.",
            method: Method::Get,
            name: "get_member_events",
            path: "/_matrix/client/r0/rooms/:room_id/members",
            rate_limited: false,
            requires_authentication: false,
            // TODO: not marked as requiring auth in the spec, but
            // will return a 403 error is user is not a member of the
            // room anyway...
        }

        request {
            /// The room to get the member events for.
            #[ruma_api(path)]
            pub room_id: RoomId,
        }

        response {
            /// A list of member events.
            pub chunk: Vec<MemberEvent>
        }
    }
}

/// [GET /_matrix/client/r0/rooms/{roomId}/messages](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-rooms-roomid-messages)
pub mod get_message_events {
    use ruma_api_macros::ruma_api;
    use ruma_events::collections::only;
    use ruma_identifiers::RoomId;

    ruma_api! {
        metadata {
            description: "Get message events for a room.",
            method: Method::Get,
            name: "get_message_events",
            path: "/_matrix/client/r0/rooms/:room_id/messages",
            rate_limited: false,
            requires_authentication: true,
        }

        request {
            /// The room to get events from.
            #[ruma_api(path)]
            pub room_id: RoomId,
            /// The token to start returning events from.
            ///
            /// This token can be obtained from a
            /// prev_batch token returned for each room by the sync API, or from a start or end token
            /// returned by a previous request to this endpoint.
            pub from: String,
            /// The token to stop returning events at.
            ///
            /// This token can be obtained from a prev_batch
            /// token returned for each room by the sync endpoint, or from a start or end token returned
            /// by a previous request to this endpoint.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub to: Option<String>,
            /// The direction to return events from.
            pub dir: Direction,
            /// The maximum number of events to return.
            ///
            /// Default: 10.
            #[serde(skip_serializing_if = "Option::is_none")]
            pub limit: Option<u64>,
        }

        response {
            /// The token the pagination starts from.
            pub start: String,
            /// A list of room events.
            pub chunk: Vec<only::RoomEvent>,
            /// The token the pagination ends at.
            pub end: String,
        }
    }

    /// The direction to return events from.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub enum Direction {
        /// Return events backwards in time from the requested `from` token.
        #[serde(rename="b")]
        Backward,
        /// Return events forwards in time from the requested `from` token.
        #[serde(rename="f")]
        Forward,
    }
}

/// [GET /_matrix/client/r0/sync](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync)
pub mod sync_events {
    use std::collections::HashMap;

    use ruma_api_macros::ruma_api;
    use ruma_events::collections::{all, only};
    use ruma_identifiers::RoomId;

    use r0::filter::FilterDefinition;

    ruma_api! {
        metadata {
            description: "Get all new events from all rooms since the last sync or a given point of time.",
            method: Method::Get,
            name: "sync",
            path: "/_matrix/client/r0/sync",
            rate_limited: false,
            requires_authentication: true,
        }

        request {
            /// A filter represented either as its full JSON definition or the ID of a saved filter.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub filter: Option<Filter>,
            /// A point in time to continue a sync from.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub since: Option<String>,
            /// Controls whether to include the full state for all rooms the user is a member of.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub full_state: Option<bool>,
            /// Controls whether the client is automatically marked as online by polling this API.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub set_presence: Option<SetPresence>,
            /// The maximum time to poll in milliseconds before returning this request.
            #[serde(skip_serializing_if = "Option::is_none")]
            #[ruma_api(query)]
            pub timeout: Option<u64>,
        }

        response {
            /// The batch token to supply in the `since` param of the next `/sync` request.
            pub next_batch: String,
            /// Updates to rooms.
            pub rooms: Rooms,
            /// Updates to the presence status of other users.
            pub presence: Presence,
        }

    }

    /// Whether to set presence or not during sync.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub enum SetPresence {
        /// Do not set the presence of the user calling this API.
        #[serde(rename="offline")]
        Offline,
    }

    /// A filter represented either as its full JSON definition or the ID of a saved filter.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    #[serde(untagged)]
    pub enum Filter {
        /// A complete filter definition serialized to JSON.
        FilterDefinition(FilterDefinition),
        /// The ID of a filter saved on the server.
        FilterId(String),
    }

    /// Updates to rooms.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct Rooms {
        /// The rooms that the user has left or been banned from.
        pub leave: HashMap<RoomId, LeftRoom>,
        /// The rooms that the user has joined.
        pub join: HashMap<RoomId, JoinedRoom>,
        /// The rooms that the user has been invited to.
        pub invite: HashMap<RoomId, InvitedRoom>,
    }

    /// Historical updates to left rooms.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct LeftRoom {
        /// The timeline of messages and state changes in the room up to the point when the user
        /// left.
        pub timeline: Timeline,
        /// The state updates for the room up to the start of the timeline.
        pub state: State,
    }

    /// Updates to joined rooms.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct JoinedRoom {
        /// Counts of unread notifications for this room.
        pub unread_notifications: UnreadNotificationsCount,
        /// The timeline of messages and state changes in the room.
        pub timeline: Timeline,
        /// Updates to the state, between the time indicated by the `since` parameter, and the start
        /// of the `timeline` (or all state up to the start of the `timeline`, if `since` is not
        /// given, or `full_state` is true).
        pub state: State,
        /// The private data that this user has attached to this room.
        pub account_data: AccountData,
        /// The ephemeral events in the room that aren't recorded in the timeline or state of the
        /// room. e.g. typing.
        pub ephemeral: Ephemeral,
    }

    /// unread notifications count
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct UnreadNotificationsCount {
        /// The number of unread notifications for this room with the highlight flag set.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub highlight_count: Option<u64>,
        /// The total number of unread notifications for this room.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub notification_count: Option<u64>,
    }

    /// Events in the room.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct Timeline {
        /// True if the number of events returned was limited by the `limit` on the filter.
        pub limited: bool,
        /// A token that can be supplied to to the `from` parameter of the
        /// `/rooms/{roomId}/messages` endpoint.
        pub prev_batch: String,
        /// A list of events.
        pub events: Vec<all::RoomEvent>,
    }

    /// State events in the room.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct State {
        /// A list of state events.
        pub events: Vec<only::StateEvent>,
    }

    /// The private data that this user has attached to this room.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct AccountData {
        /// A list of events.
        pub events: Vec<only::Event>,
    }

    /// Ephemeral events not recorded in the timeline or state of the room.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct Ephemeral {
        /// A list of events.
        pub events: Vec<only::Event>,
    }

    /// Updates to the rooms that the user has been invited to.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct InvitedRoom {
        /// The state of a room that the user has been invited to.
        pub invite_state: InviteState,
    }

    /// The state of a room that the user has been invited to.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct InviteState {
        /// A list of state events.
        pub events: Vec<only::StateEvent>,
    }

    /// Updates to the presence status of other users.
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct Presence {
        /// A list of events.
        pub events: Vec<only::Event>,
    }
}
<|endoftext|>


<commit_before>use byteread::*;

pub trait BitReadEndian {
    fn peek_val(&mut self, n:usize) -> u64;
    fn merge_val(msp:u64, lsp:u64, msb:usize, lsb:usize) -> u64;
    fn skip_rem(&mut self, n:usize) -> ();
    fn fill32(&self) -> u64;
    fn fill64(&self) -> u64;
}

pub trait BitReadInternal : BitReadEndian {
    #[inline]
    fn left(&self) -> usize;
    fn refill32(&mut self) -> ();
    fn refill64(&mut self) -> ();

    fn get_val(&mut self, n:usize) -> u64 {
        let ret = self.peek_val(n);

        self.skip_rem(n);

        return ret;
    }

}

pub trait BitRead<'a>: BitReadInternal+Copy {
    fn new(&'a[u8]) -> Self;
    fn consumed(&self) -> usize;
    fn available(&self) -> usize;
    fn can_refill(&self) -> bool;

    fn skip_bits(&mut self, size : usize) -> ();

    #[inline]
    fn get_bit(&mut self) -> bool {
        if self.left() <= 0 {
            self.refill64();
        }

        self.get_val(1) != 0
    }

    #[inline]
    fn get_bits_64(&mut self, mut n:usize) -> u64 {
        let mut left = 0;
        let mut ret = 0;

        if n == 0 {
            return 0;
        }

        if self.left() < n {
            n   -= self.left();
            left = self.left();
            ret  = self.get_val(left);
            self.refill64();
        }

        Self::merge_val(self.get_val(n), ret, left, n)
    }

    #[inline]
    fn get_bits_32(&mut self, n:usize) -> u32 {
        if n == 0 {
            return 0;
        }

        if self.left() <= n {
            self.refill32();
        }

        return self.get_val(n) as u32;
    }

    #[inline]
    fn peek_bit(&mut self) -> bool {
        let mut tmp = *self;

        tmp.get_bit()
    }

    #[inline]
    fn peek_bits_32(&mut self, n:usize) -> u32 {
        let mut tmp = *self;

        tmp.get_bits_32(n)
    }

    #[inline]
    fn peek_bits_64(&self, n:usize) -> u64 {
        let mut tmp = *self;

        tmp.get_bits_64(n)
    }

    #[inline]
    fn align_bits(&mut self) -> () {
        let left = self.left() & 7;

        self.skip_bits(left);
    }
}

macro_rules! endian_reader {
    {$name: ident} => {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<'a> {
            buffer : &'a[u8], /// read buffer, 8-bytes padded
            index : usize,
            cache : u64,
            left : usize,
        }
        impl <'a> BitReadInternal for $name<'a> {
            #[inline]
            fn left(&self) -> usize {
                self.left
            }
            #[inline]
            fn refill32(&mut self) -> () {
                if !self.can_refill() {
                    return;
                }
                let val = self.fill32();

                self.cache  = Self::merge_val(val, self.cache,
                                              self.left, 32 - self.left);
                self.index += 4;
                self.left  += 32;
            }
            #[inline]
            fn refill64(&mut self) -> () {
                if !self.can_refill() {
                    return;
                }

                self.cache  = self.fill64();
                self.index += 8;
                self.left   = 64;
            }
        }

        impl <'a> BitRead<'a> for $name<'a> {
            fn new(buffer: &'a[u8]) -> $name<'a> {
                let mut reader = $name {
                    buffer: buffer,
                    index: 0,
                    cache: 0,
                    left: 0
                };

                reader.refill64();
                return reader;
            }
            #[inline]
            fn consumed(&self) -> usize {
                self.index * 8 - self.left
            }

            #[inline]
            fn available(&self) -> usize {
                (self.buffer.len() - self.index) * 8 + self.left
            }

            #[inline]
            fn can_refill(&self) -> bool {
                self.index + 8 <= self.buffer.len()
            }

            #[inline]
            fn skip_bits(&mut self, mut n:usize) -> () {
                if self.left < n {
                    n -= self.left;
                    if n > 64 {
                        let skip = n / 8;

                        n -= skip * 8;
                        self.index += skip;
                    }
                    self.skip_rem(n);
                    self.refill64();
                }

                self.skip_rem(n);
            }

        }
    }
}

endian_reader!{ BitReadLE }

impl <'a> BitReadEndian for BitReadLE<'a> {
    #[inline]
    fn peek_val(&mut self, n:usize) -> u64 {
        let v = self.cache & ((1u64 << n) - 1);

        return v;
    }
    #[inline]
    fn skip_rem(&mut self, n:usize) -> () {
        self.cache = self.cache >> n;
        self.left = self.left.saturating_sub(n);
    }
    #[inline]
    fn merge_val(msp:u64, lsp:u64, msb:usize, _:usize) -> u64 {
        msp << msb | lsp
    }
    #[inline(always)]
    fn fill32(&self) -> u64 {
        get_u32l(&self.buffer[self.index..]) as u64
    }
    #[inline(always)]
    fn fill64(&self) -> u64 {
        get_u64l(&self.buffer[self.index..])
    }
}

endian_reader!{ BitReadBE }

impl <'a> BitReadEndian for BitReadBE<'a> {
    #[inline]
    fn peek_val(&mut self, n:usize) -> u64 {
        self.cache >> (64 - n)
    }
    #[inline]
    fn skip_rem(&mut self, n:usize) -> () {
        self.cache = self.cache << n;
        self.left = self.left.saturating_sub(n);
    }
    #[inline]
    fn merge_val(msp:u64, lsp:u64, _:usize, lsb:usize) -> u64 {
        msp | lsp << lsb
    }
    #[inline(always)]
    fn fill32(&self) -> u64 {
        get_u32b(&self.buffer[self.index..]) as u64
    }
    #[inline(always)]
    fn fill64(&self) -> u64 {
        get_u64b(&self.buffer[self.index..])
    }
}

#[cfg(test)]
mod test {
    pub const CHECKBOARD0101: [u8; 128] = [0b01010101; 128];
    pub const CHECKBOARD0011: [u8; 128] = [0b00110011; 128];

    mod le {
        use super::super::*;
        use super::*;

        #[test]
        fn get_bit() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            assert!(reader.get_bit());
            assert!(!reader.get_bit());
        }

        #[test]
        fn get_bits_64() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            assert!(reader.get_bits_64(1) == 1);
            assert!(reader.get_bits_64(2) == 2);
            assert!(reader.get_bits_64(4) == 10);
            assert!(reader.get_bits_64(1) == 0);
            assert!(reader.get_bits_64(8) == 85);
        }

        #[test]
        fn peek_bits_64() {
            let reader = BitReadLE {
                buffer: &CHECKBOARD0101,
                index: 0,
                cache: 0,
                left: 0
            };

            assert!(reader.peek_bits_64(1) == 1);
            assert!(reader.peek_bits_64(1) == 1);
            assert!(reader.peek_bits_64(2) == 1);
            assert!(reader.peek_bits_64(2) == 1);
        }

        #[test]
        fn get_bits_32() {
            let mut reader = BitReadLE {
                buffer: &CHECKBOARD0101,
                index: 0,
                cache: 0,
                left: 0
            };

            assert!(reader.get_bits_32(1) == 1);
            assert!(reader.get_bits_32(2) == 2);
            assert!(reader.get_bits_32(4) == 10);
            assert!(reader.get_bits_32(1) == 0);
            assert!(reader.get_bits_32(8) == 85);
        }

        #[test]
        fn peek_bits_32() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            assert!(reader.peek_bits_32(1) == 1);
            assert!(reader.peek_bits_32(1) == 1);
            assert!(reader.peek_bits_32(2) == 1);
            assert!(reader.peek_bits_32(2) == 1);
        }

        #[test]
        fn skip_bits() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            reader.skip_bits(0);
            assert!(reader.peek_bits_32(1) == 1);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 1);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 1);
        }

        #[test]
        fn align_bits() {
            let b = &CHECKBOARD0011;
            let mut reader = BitReadLE::new(b);

            reader.align_bits();
            assert!(reader.get_bits_64(3) == 3);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
            reader.skip_bits(1);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
        }

        #[test]
        fn overread() {
            let b = &CHECKBOARD0011;
            let mut reader = BitReadLE::new(b);

            reader.skip_bits(128*8+2);
            reader.get_bits_64(6);
        }
    }
    mod be {
        use super::super::*;
        use super::*;

        #[test]
        fn get_bit() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(!reader.get_bit());
            assert!(reader.get_bit());
        }

        #[test]
        fn get_bits_64() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(reader.get_bits_64(1) == 0);
            assert!(reader.get_bits_64(2) == 2);
            assert!(reader.get_bits_64(4) == 10);
            assert!(reader.get_bits_64(1) == 1);
            assert!(reader.get_bits_64(8) == 85);
        }

        #[test]
        fn peek_bits_64() {
            let b = &CHECKBOARD0101;
            let reader = BitReadBE::new(b);

            assert!(reader.peek_bits_64(1) == 0);
            assert!(reader.peek_bits_64(1) == 0);
            assert!(reader.peek_bits_64(2) == 1);
            assert!(reader.peek_bits_64(2) == 1);
        }

        #[test]
        fn get_bits_32() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(reader.get_bits_32(1) == 0);
            assert!(reader.get_bits_32(2) == 2);
            assert!(reader.get_bits_32(4) == 10);
            assert!(reader.get_bits_32(1) == 1);
            assert!(reader.get_bits_32(8) == 85);
        }

        #[test]
        fn peek_bits_32() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(reader.peek_bits_32(1) == 0);
            assert!(reader.peek_bits_32(1) == 0);
            assert!(reader.peek_bits_32(2) == 1);
            assert!(reader.peek_bits_32(2) == 1);
        }

        #[test]
        fn skip_bits() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            reader.skip_bits(0);
            assert!(reader.peek_bits_32(1) == 0);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 0);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 0);
        }

        #[test]
        fn align_bits() {
            let b = &CHECKBOARD0011;
            let mut reader = BitReadBE::new(b);

            reader.align_bits();
            assert!(reader.get_bits_64(3) == 1);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
            reader.skip_bits(1);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
        }

        #[test]
        fn overread() {
            let b = &CHECKBOARD0011;
            let mut reader = BitReadBE::new(b);

            reader.skip_bits(128*8+2);
            reader.get_bits_64(6);
        }
    }
}
<commit_msg>bitstream: Refactor the bitreader<commit_after>use byteread::*;

pub trait BitReadEndian {
    fn peek_val(&mut self, n:usize) -> u64;
    fn merge_val(msp:u64, lsp:u64, msb:usize, lsb:usize) -> u64;
    fn skip_rem(&mut self, n:usize) -> ();
}

pub trait BitReadFill {
    fn fill32(&self) -> u64;
    fn fill64(&self) -> u64;
}

pub trait BitReadInternal : BitReadEndian + BitReadFill {
    #[inline]
    fn left(&self) -> usize;
    fn refill32(&mut self) -> ();
    fn refill64(&mut self) -> ();

    fn get_val(&mut self, n:usize) -> u64 {
        let ret = self.peek_val(n);

        self.skip_rem(n);

        return ret;
    }

}

pub trait BitRead<'a>: BitReadInternal+Copy {
    fn new(&'a[u8]) -> Self;
    fn consumed(&self) -> usize;
    fn available(&self) -> usize;
    fn can_refill(&self) -> bool;

    fn skip_bits(&mut self, size : usize) -> ();

    #[inline]
    fn get_bit(&mut self) -> bool {
        if self.left() <= 0 {
            self.refill64();
        }

        self.get_val(1) != 0
    }

    #[inline]
    fn get_bits_64(&mut self, mut n:usize) -> u64 {
        let mut left = 0;
        let mut ret = 0;

        if n == 0 {
            return 0;
        }

        if self.left() < n {
            n   -= self.left();
            left = self.left();
            ret  = self.get_val(left);
            self.refill64();
        }

        Self::merge_val(self.get_val(n), ret, left, n)
    }

    #[inline]
    fn get_bits_32(&mut self, n:usize) -> u32 {
        if n == 0 {
            return 0;
        }

        if self.left() <= n {
            self.refill32();
        }

        return self.get_val(n) as u32;
    }

    #[inline]
    fn peek_bit(&mut self) -> bool {
        let mut tmp = *self;

        tmp.get_bit()
    }

    #[inline]
    fn peek_bits_32(&mut self, n:usize) -> u32 {
        let mut tmp = *self;

        tmp.get_bits_32(n)
    }

    #[inline]
    fn peek_bits_64(&self, n:usize) -> u64 {
        let mut tmp = *self;

        tmp.get_bits_64(n)
    }

    #[inline]
    fn align_bits(&mut self) -> () {
        let left = self.left() & 7;

        self.skip_bits(left);
    }
}

macro_rules! endian_reader {
    {$name: ident} => {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<'a> {
            buffer : &'a[u8], /// read buffer, 8-bytes padded
            index : usize,
            cache : u64,
            left : usize,
        }
        impl <'a> BitReadInternal for $name<'a> {
            #[inline]
            fn left(&self) -> usize {
                self.left
            }
            #[inline]
            fn refill32(&mut self) -> () {
                if !self.can_refill() {
                    return;
                }
                let val = self.fill32();

                self.cache  = Self::merge_val(val, self.cache,
                                              self.left, 32 - self.left);
                self.index += 4;
                self.left  += 32;
            }
            #[inline]
            fn refill64(&mut self) -> () {
                if !self.can_refill() {
                    return;
                }

                self.cache  = self.fill64();
                self.index += 8;
                self.left   = 64;
            }
        }

        impl <'a> BitRead<'a> for $name<'a> {
            fn new(buffer: &'a[u8]) -> $name<'a> {
                let mut reader = $name {
                    buffer: buffer,
                    index: 0,
                    cache: 0,
                    left: 0
                };

                reader.refill64();
                return reader;
            }
            #[inline]
            fn consumed(&self) -> usize {
                self.index * 8 - self.left
            }

            #[inline]
            fn available(&self) -> usize {
                (self.buffer.len() - self.index) * 8 + self.left
            }

            #[inline]
            fn can_refill(&self) -> bool {
                self.index + 8 <= self.buffer.len()
            }

            #[inline]
            fn skip_bits(&mut self, mut n:usize) -> () {
                if self.left < n {
                    n -= self.left;
                    if n > 64 {
                        let skip = n / 8;

                        n -= skip * 8;
                        self.index += skip;
                    }
                    self.skip_rem(n);
                    self.refill64();
                }

                self.skip_rem(n);
            }

        }
    }
}

macro_rules! little_endian_reader {
    {$name: ident} => {
        endian_reader!{ $name }

        impl <'a> BitReadEndian for $name<'a> {
            #[inline]
            fn peek_val(&mut self, n:usize) -> u64 {
                let v = self.cache & ((1u64 << n) - 1);

                return v;
            }
            #[inline]
            fn skip_rem(&mut self, n:usize) -> () {
                self.cache = self.cache >> n;
                self.left = self.left.saturating_sub(n);
            }
            #[inline]
            fn merge_val(msp:u64, lsp:u64, msb:usize, _:usize) -> u64 {
                msp << msb | lsp
            }
        }
    }
}

little_endian_reader!{ BitReadLE }

impl <'a> BitReadFill for BitReadLE<'a> {
    #[inline(always)]
    fn fill32(&self) -> u64 {
        get_u32l(&self.buffer[self.index..]) as u64
    }
    #[inline(always)]
    fn fill64(&self) -> u64 {
        get_u64l(&self.buffer[self.index..])
    }
}

macro_rules! big_endian_reader {
    {$name: ident} => {
        endian_reader!{ $name }

        impl <'a> BitReadEndian for $name<'a> {
            #[inline]
            fn peek_val(&mut self, n:usize) -> u64 {
                self.cache >> (64 - n)
            }
            #[inline]
            fn skip_rem(&mut self, n:usize) -> () {
                self.cache = self.cache << n;
                self.left = self.left.saturating_sub(n);
            }
            #[inline]
            fn merge_val(msp:u64, lsp:u64, _:usize, lsb:usize) -> u64 {
                msp | lsp << lsb
            }
        }
    }
}

big_endian_reader!{ BitReadBE }

impl <'a> BitReadFill for BitReadBE<'a> {
    #[inline(always)]
    fn fill32(&self) -> u64 {
        get_u32b(&self.buffer[self.index..]) as u64
    }
    #[inline(always)]
    fn fill64(&self) -> u64 {
        get_u64b(&self.buffer[self.index..])
    }
}

#[cfg(test)]
mod test {
    pub const CHECKBOARD0101: [u8; 128] = [0b01010101; 128];
    pub const CHECKBOARD0011: [u8; 128] = [0b00110011; 128];

    mod le {
        use super::super::*;
        use super::*;

        #[test]
        fn get_bit() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            assert!(reader.get_bit());
            assert!(!reader.get_bit());
        }

        #[test]
        fn get_bits_64() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            assert!(reader.get_bits_64(1) == 1);
            assert!(reader.get_bits_64(2) == 2);
            assert!(reader.get_bits_64(4) == 10);
            assert!(reader.get_bits_64(1) == 0);
            assert!(reader.get_bits_64(8) == 85);
        }

        #[test]
        fn peek_bits_64() {
            let reader = BitReadLE {
                buffer: &CHECKBOARD0101,
                index: 0,
                cache: 0,
                left: 0
            };

            assert!(reader.peek_bits_64(1) == 1);
            assert!(reader.peek_bits_64(1) == 1);
            assert!(reader.peek_bits_64(2) == 1);
            assert!(reader.peek_bits_64(2) == 1);
        }

        #[test]
        fn get_bits_32() {
            let mut reader = BitReadLE {
                buffer: &CHECKBOARD0101,
                index: 0,
                cache: 0,
                left: 0
            };

            assert!(reader.get_bits_32(1) == 1);
            assert!(reader.get_bits_32(2) == 2);
            assert!(reader.get_bits_32(4) == 10);
            assert!(reader.get_bits_32(1) == 0);
            assert!(reader.get_bits_32(8) == 85);
        }

        #[test]
        fn peek_bits_32() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            assert!(reader.peek_bits_32(1) == 1);
            assert!(reader.peek_bits_32(1) == 1);
            assert!(reader.peek_bits_32(2) == 1);
            assert!(reader.peek_bits_32(2) == 1);
        }

        #[test]
        fn skip_bits() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadLE::new(b);

            reader.skip_bits(0);
            assert!(reader.peek_bits_32(1) == 1);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 1);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 1);
        }

        #[test]
        fn align_bits() {
            let b = &CHECKBOARD0011;
            let mut reader = BitReadLE::new(b);

            reader.align_bits();
            assert!(reader.get_bits_64(3) == 3);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
            reader.skip_bits(1);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
        }

        #[test]
        fn overread() {
            let b = &CHECKBOARD0011;
            let mut reader = BitReadLE::new(b);

            reader.skip_bits(128*8+2);
            reader.get_bits_64(6);
        }
    }
    mod be {
        use super::super::*;
        use super::*;

        #[test]
        fn get_bit() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(!reader.get_bit());
            assert!(reader.get_bit());
        }

        #[test]
        fn get_bits_64() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(reader.get_bits_64(1) == 0);
            assert!(reader.get_bits_64(2) == 2);
            assert!(reader.get_bits_64(4) == 10);
            assert!(reader.get_bits_64(1) == 1);
            assert!(reader.get_bits_64(8) == 85);
        }

        #[test]
        fn peek_bits_64() {
            let b = &CHECKBOARD0101;
            let reader = BitReadBE::new(b);

            assert!(reader.peek_bits_64(1) == 0);
            assert!(reader.peek_bits_64(1) == 0);
            assert!(reader.peek_bits_64(2) == 1);
            assert!(reader.peek_bits_64(2) == 1);
        }

        #[test]
        fn get_bits_32() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(reader.get_bits_32(1) == 0);
            assert!(reader.get_bits_32(2) == 2);
            assert!(reader.get_bits_32(4) == 10);
            assert!(reader.get_bits_32(1) == 1);
            assert!(reader.get_bits_32(8) == 85);
        }

        #[test]
        fn peek_bits_32() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            assert!(reader.peek_bits_32(1) == 0);
            assert!(reader.peek_bits_32(1) == 0);
            assert!(reader.peek_bits_32(2) == 1);
            assert!(reader.peek_bits_32(2) == 1);
        }

        #[test]
        fn skip_bits() {
            let b = &CHECKBOARD0101;
            let mut reader = BitReadBE::new(b);

            reader.skip_bits(0);
            assert!(reader.peek_bits_32(1) == 0);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 0);
            reader.skip_bits(2);
            assert!(reader.peek_bits_32(1) == 0);
        }

        #[test]
        fn align_bits() {
            let b = &CHECKBOARD0011;
            let mut reader = BitReadBE::new(b);

            reader.align_bits();
            assert!(reader.get_bits_64(3) == 1);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
            reader.skip_bits(1);
            reader.align_bits();
            assert!(reader.get_bits_64(4) == 3);
        }

        #[test]
        fn overread() {
            let b = &CHECKBOARD0011;
            let mut reader = BitReadBE::new(b);

            reader.skip_bits(128*8+2);
            reader.get_bits_64(6);
        }
    }
}
<|endoftext|>


<commit_before>
use std::rc::Rc;
use std::cell::RefCell;
use std::ops::{ Deref, DerefMut };

use GetFrom;
use SetAt;
use ActOn;
use Pair;
use Associative;

impl<T, U> GetFrom for (U, Box<T>)
    where
        (U, T): Pair<Data = U, Object = T> + GetFrom
{
    #[inline(always)]
    fn get_from(obj: &Box<T>) -> U {
        <(U, T) as GetFrom>::get_from(obj)
    }
}

impl<'a, T, U> GetFrom for (U, &'a RefCell<T>)
    where
        (U, T): Pair<Data = U, Object = T> + GetFrom
{
    #[inline(always)]
    fn get_from(obj: &&'a RefCell<T>) -> U {
        <(U, T) as GetFrom>::get_from(obj.borrow().deref())
    }
}

impl<T, U> GetFrom for (U, Rc<RefCell<T>>)
    where
        (U, T): Pair<Data = U, Object = T> + GetFrom
{
    #[inline(always)]
    fn get_from(obj: &Rc<RefCell<T>>) -> U {
        <(U, T) as GetFrom>::get_from(obj.borrow().deref())
    }
}

impl<F, T> SetAt for (T, Box<F>)
    where
        (T, F): Pair<Data = T, Object = F> + SetAt
{
    #[inline(always)]
    fn set_at(val: T, obj: &mut Box<F>) {
        <(T, F) as SetAt>::set_at(val, obj)
    }
}

impl<'a, F, T> SetAt for (T, &'a RefCell<F>)
    where
        (T, F): Pair<Data = T, Object = F> + SetAt
{
    #[inline(always)]
    fn set_at(val: T, obj: &mut &'a RefCell<F>) {
        <(T, F) as SetAt>::set_at(val, obj.borrow_mut().deref_mut())
    }
}

impl<F, T> SetAt for (T, Rc<RefCell<F>>)
    where
        (T, F): Pair<Data = T, Object = F> + SetAt
{
    #[inline(always)]
    fn set_at(val: T, obj: &mut Rc<RefCell<F>>) {
        <(T, F) as SetAt>::set_at(val, obj.borrow_mut().deref_mut())
    }
}

impl<F, A> ActOn for (A, Box<F>)
    where
        (A, F): Pair<Data = A, Object = F> + ActOn
{
    type Result = <(A, F) as ActOn>::Result;

    #[inline(always)]
    fn act_on(
        action: A,
        obj: &mut Box<F>
    ) -> <(A, F) as ActOn>::Result {
        <(A, F) as ActOn>::act_on(action, obj)
    }
}

impl<'a, F, A> ActOn for (A, &'a RefCell<F>)
    where
        (A, F): Pair<Data = A, Object = F> + ActOn
{
    type Result = <(A, F) as ActOn>::Result;

    #[inline(always)]
    fn act_on(
        action: A,
        obj: &mut &'a RefCell<F>
    ) -> <(A, F) as ActOn>::Result {
        <(A, F) as ActOn>::act_on(action, obj.borrow_mut().deref_mut())
    }
}

impl<F, A> ActOn for (A, Rc<RefCell<F>>)
    where
        (A, F): Pair<Data = A, Object = F> + ActOn
{
    type Result = <(A, F) as ActOn>::Result;

    #[inline(always)]
    fn act_on(
        action: A,
        obj: &mut Rc<RefCell<F>>
    ) -> <(A, F) as ActOn>::Result {
        <(A, F) as ActOn>::act_on(action, obj.borrow_mut().deref_mut())
    }
}

impl<F, A> Associative for (A, Box<F>)
    where
        (A, F): Pair<Data = A, Object = F> + Associative
{
    type Type = <(A, F) as Associative>::Type;
}

impl<'a, F, A> Associative for (A, &'a RefCell<F>)
    where
        (A, F): Pair<Data = A, Object = F> + Associative
{
    type Type = <(A, F) as Associative>::Type;
}

impl<F, A> Associative for (A, Rc<RefCell<F>>)
    where
        (A, F): Pair<Data = A, Object = F> + Associative
{
    type Type = <(A, F) as Associative>::Type;
}
<commit_msg>Implemented traits for &mut T<commit_after>
use std::rc::Rc;
use std::cell::RefCell;
use std::ops::{ Deref, DerefMut };

use GetFrom;
use SetAt;
use ActOn;
use Pair;
use Associative;

impl<'a, T, U> GetFrom for (U, &'a mut T)
    where
        (U, T): Pair<Data = U, Object = T> + GetFrom
{
    #[inline(always)]
    fn get_from(obj: &&'a mut T) -> U {
        <(U, T) as GetFrom>::get_from(obj)
    }
}

impl<T, U> GetFrom for (U, Box<T>)
    where
        (U, T): Pair<Data = U, Object = T> + GetFrom
{
    #[inline(always)]
    fn get_from(obj: &Box<T>) -> U {
        <(U, T) as GetFrom>::get_from(obj)
    }
}

impl<'a, T, U> GetFrom for (U, &'a RefCell<T>)
    where
        (U, T): Pair<Data = U, Object = T> + GetFrom
{
    #[inline(always)]
    fn get_from(obj: &&'a RefCell<T>) -> U {
        <(U, T) as GetFrom>::get_from(obj.borrow().deref())
    }
}

impl<T, U> GetFrom for (U, Rc<RefCell<T>>)
    where
        (U, T): Pair<Data = U, Object = T> + GetFrom
{
    #[inline(always)]
    fn get_from(obj: &Rc<RefCell<T>>) -> U {
        <(U, T) as GetFrom>::get_from(obj.borrow().deref())
    }
}

impl<'a, F, T> SetAt for (T, &'a mut F)
    where
        (T, F): Pair<Data = T, Object = F> + SetAt
{
    #[inline(always)]
    fn set_at(val: T, obj: &mut &'a mut F) {
        <(T, F) as SetAt>::set_at(val, obj)
    }
}

impl<F, T> SetAt for (T, Box<F>)
    where
        (T, F): Pair<Data = T, Object = F> + SetAt
{
    #[inline(always)]
    fn set_at(val: T, obj: &mut Box<F>) {
        <(T, F) as SetAt>::set_at(val, obj)
    }
}

impl<'a, F, T> SetAt for (T, &'a RefCell<F>)
    where
        (T, F): Pair<Data = T, Object = F> + SetAt
{
    #[inline(always)]
    fn set_at(val: T, obj: &mut &'a RefCell<F>) {
        <(T, F) as SetAt>::set_at(val, obj.borrow_mut().deref_mut())
    }
}

impl<F, T> SetAt for (T, Rc<RefCell<F>>)
    where
        (T, F): Pair<Data = T, Object = F> + SetAt
{
    #[inline(always)]
    fn set_at(val: T, obj: &mut Rc<RefCell<F>>) {
        <(T, F) as SetAt>::set_at(val, obj.borrow_mut().deref_mut())
    }
}

impl<'a, F, A> ActOn for (A, &'a mut F)
    where
        (A, F): Pair<Data = A, Object = F> + ActOn
{
    type Result = <(A, F) as ActOn>::Result;

    #[inline(always)]
    fn act_on(
        action: A,
        obj: &mut &'a mut F
    ) -> <(A, F) as ActOn>::Result {
        <(A, F) as ActOn>::act_on(action, obj)
    }
}

impl<F, A> ActOn for (A, Box<F>)
    where
        (A, F): Pair<Data = A, Object = F> + ActOn
{
    type Result = <(A, F) as ActOn>::Result;

    #[inline(always)]
    fn act_on(
        action: A,
        obj: &mut Box<F>
    ) -> <(A, F) as ActOn>::Result {
        <(A, F) as ActOn>::act_on(action, obj)
    }
}

impl<'a, F, A> ActOn for (A, &'a RefCell<F>)
    where
        (A, F): Pair<Data = A, Object = F> + ActOn
{
    type Result = <(A, F) as ActOn>::Result;

    #[inline(always)]
    fn act_on(
        action: A,
        obj: &mut &'a RefCell<F>
    ) -> <(A, F) as ActOn>::Result {
        <(A, F) as ActOn>::act_on(action, obj.borrow_mut().deref_mut())
    }
}

impl<F, A> ActOn for (A, Rc<RefCell<F>>)
    where
        (A, F): Pair<Data = A, Object = F> + ActOn
{
    type Result = <(A, F) as ActOn>::Result;

    #[inline(always)]
    fn act_on(
        action: A,
        obj: &mut Rc<RefCell<F>>
    ) -> <(A, F) as ActOn>::Result {
        <(A, F) as ActOn>::act_on(action, obj.borrow_mut().deref_mut())
    }
}

impl<'a, F, A> Associative for (A, &'a mut F)
    where
        (A, F): Pair<Data = A, Object = F> + Associative
{
    type Type = <(A, F) as Associative>::Type;
}

impl<F, A> Associative for (A, Box<F>)
    where
        (A, F): Pair<Data = A, Object = F> + Associative
{
    type Type = <(A, F) as Associative>::Type;
}

impl<'a, F, A> Associative for (A, &'a RefCell<F>)
    where
        (A, F): Pair<Data = A, Object = F> + Associative
{
    type Type = <(A, F) as Associative>::Type;
}

impl<F, A> Associative for (A, Rc<RefCell<F>>)
    where
        (A, F): Pair<Data = A, Object = F> + Associative
{
    type Type = <(A, F) as Associative>::Type;
}
<|endoftext|>


<commit_before>use engine::Name;
use macros::ProgPt;
use std::fmt::Debug;
//use std::hash::Hash;
use std::rc::Rc;
use std::collections::HashMap;

/// Reflected primitive data
pub trait Data : Debug { }

pub trait Reflect<T> : Debug {
  fn reflect (&self) -> T;
}

impl<S,T:Reflect<S>+Debug> Reflect<Option<S>> for Option<T> {
  fn reflect (&self) -> Option<S> {
    match *self {
      None => None,
      Some(ref x) => Some(x.reflect())
    }
  }
}

impl<'a,S,T:Reflect<S>+Debug> Reflect<S> for &'a Rc<T> {
  fn reflect (&self) -> S {
    (**self).reflect()
  }
}

impl<'a,S,T:Reflect<S>+Debug> Reflect<S> for Rc<T> {
  fn reflect (&self) -> S {
    (**self).reflect()
  }
}

/// Reflected value; Gives a syntax for inductive data type
/// constructors (`Constr`), named articulations (`Art`) and primitive
/// data (`Data).
#[derive(Debug,Clone)]
pub enum Val {
  /// Constructor, with value parameters.
  Constr(Name,Vec<Val>),
  /// Named articulation, and its content (an `Art` is either a named value, or a named computation).
  Art(Name,ArtContent),
  /// Primitive, immutable data.
  Data(Rc<Data>),

  /// Temporary; for marking places in code where we should produce a
  /// value, but don't yet have a good way to do so.
  ValTODO,
}

/// The content of an articulation: Either a cell holding a value, or
/// a thunk that has optionally produced a value.
#[derive(Debug,Clone)]
pub enum ArtContent {
  /// A cell holding a value
  Val(Rc<Val>),
  /// A thunk that, when forced, computes a value
  Comp(Option<Rc<Val>>),
}

/// `Reflected version of engine::Loc` A `Loc` is a particular
/// template for a `Name`: It is a path (a possibly-empty list of
/// `Name`s), followed by a distinguished `Name`.  A `Loc` can be
/// thought of roughly like a file path in UNIX (but Adapton has
/// nothing to do with files, or with UNIX, directly).
#[derive(PartialEq,Eq,Debug,Hash,Clone)]
pub struct Loc {
  /// The path of the `Loc` is a list of `Name`s.
  pub path: Path,
  /// The distinguished `Name` of the `Loc` (must be unique in the path).
  pub name: Name,
}

/// A `Path` here is just a `Vec` of `Name`s
pub type Path = Vec<Name>;

/// `Reflected version of engine::Effect`
#[derive(Debug,Clone)]
pub enum Effect {
  /// The effect consists of a thunk observing the value of another
  /// thunk or reference cell.  That is, the effect consists of
  /// **consuming** a value, by demanding its production.
  Force,
  /// The effect consists of a thunk allocating a value or thunk at a
  /// particular name.  That is, the effect consists of **producing**
  /// a value or computation.  If this content differs, then the
  /// allocation is a **reallocation**, and the engine dirties the old
  /// observers and allocators of the preceding content.
  Alloc,
}

/// Reflected version of `engine::Succ`
#[derive(Debug,Clone)]
pub struct Succ {
  /// Dirty invariant: If this edge is dirty, then all predecessors of
  /// the edge are dirty too.
  pub dirty:  bool,
  /// The target of the outgoing `Effect`
  pub loc:    Loc,
  /// The effect: either producing or consuming articulated content
  pub effect: Effect,
  /// The value either produced or consumed by this `Effect`
  pub value:  Val,
}

impl Reflect<Succ> for Succ {
  fn reflect (&self) -> Succ {
    self.clone()
  }
}

/// Reflected version of `engine::Pred`
#[derive(Debug)]
pub struct Pred {
  /// The predecessor of the node in question
  pub loc:    Loc,
  /// The effect that the predecessor has done to the node in question
  pub effect: Effect,
}

/// Reflected version of `engine::CompNode`
#[derive(Debug)]
pub struct CompNode {
  pub preds:   Vec<Pred>,
  pub succs:   Vec<Succ>,
  pub prog_pt: ProgPt,
  pub value:   Option<Val>,
}

/// Reflected version of `engine::MutNode`
#[derive(Debug)]
pub struct RefNode {
  pub preds: Vec<Pred>,
  pub value: Val,
}

/// Reflected version of `engine::PureNode`
#[derive(Debug)]
pub struct PureNode {
  pub value: Val,
}

/// Reflected version of `engine::GraphNode`
#[derive(Debug)]
pub enum GraphNode {
  Comp(CompNode),
  Ref(RefNode),
  Pure(PureNode),
}

/// Reflected version of `engine::Frame`
#[derive(Debug)]
pub struct Frame {
  pub loc:   Loc,
  pub succs: Vec<Succ>,
}

/// Reflected version of `engine::DCG`
#[derive(Debug)]
pub struct DCG {
  /// The current memo table, mapping `Loc`s to `GraphNode`s.

  pub table: HashMap<Loc, Box<GraphNode>>,
  pub stack: Vec<Frame>,
  pub path:  Vec<Name>,
}

#[derive(Debug)]
pub enum DCGAlloc {
  /// The allocation was **created** fresh; it was **not** reused.
  LocFresh,
  /// The allocation matched the location of a prior allocation. its
  /// content may or may not also match.  The `bool` indicates the two
  /// cases: `true` means same content, `false` means changed content.
  LocExists,
}

/// When the program `force`s a computation, either the cache is
/// either empty (`CacheMiss`) or non-empty (`CacheHit`).  The cached
/// value may not be consistent without a cleaning.  When the program
/// `force`s a reference cell, it simply gets the current value.
#[derive(Debug)]
pub enum DCGForce {
  /// The DCG has no cached value for this computation; no prior
  /// computation will be reused.
  CompCacheMiss,
  /// The DCG has a cached value for this computation; it may not be
  /// consistent without a cleaning first.
  CompCacheHit,
  /// The forced node is a ref cell with a (mutable) value, and hence,
  /// no computation was necessary.  The `force` simply gets the
  /// current value.
  RefGet,
}

/// The effects of the DCG (including cleaning and dirtying) on one of
/// its edges.
#[derive(Debug)]
pub enum DCGEffect {
  /// Wrapper for Effect::Alloc; transition to DCG after the alloc.
  Alloc (DCGAlloc),

  /// Wrapper for Effect::Force; transition to DCG after the force.
  Force (DCGForce),

  /// Transition to this edge as **dirty** (potentially inconsistent).
  /// This transition may consist of marking other edges dirty.  The
  /// DCG's invariant about dirty edges is simple: If an edge is
  /// dirty, then all edges that force (demand/observe) the source of
  /// that edge must also be dirty.  This transitive closure property
  /// ensures that we do not accidentally reuse stale cached values by
  /// mistake (a dirty edge will always witness a potentially stale
  /// cached value).
  Dirty,

  /// Clean this edge, marking it not dirty, or **definitely
  /// consistent**. Cleaning consists of processing the edges dirty
  /// dependencies, if any.  Recursively, this processing may consist
  /// of marking other edges clean (`CleanEdge`), and/or, removing
  /// edges (`Remove`) and replacing them via reevaluation under the
  /// current DCG state (`CleanEval`).
  CleanRec,

  /// Re-evaluate a previously-forced thunk, to clean it.
  CleanEval,

  /// Transition to this edge as **clean** (definitely consistent),
  /// after doing a recursive cleaning of its dependencies and finding
  /// that they are clean.
  CleanEdge,

  /// Transition to the DCG without this edge.  Perhaps it will be
  /// replaced via re-execution, sometime later.
  Remove,
}

/// An adge in the DCG, representing an effect of the incremental program.
#[derive(Debug)]
pub struct DCGEdge {
  /// The source of the directed edge; it is actively _doing_ the
  /// effect of `succ.effect` to `succ.loc`.  `None` means the doer is
  /// the **editor**, who is not identified by any location. (The editor
  /// is not a node in the DCG, but rather, an actor operating outside
  /// of it).
  pub loc: Option<Loc>,
  /// The effect and target of the directed edge.
  pub succ: Succ,
}

/// `DCGTrace`: A Rose-tree of DCG edge-effects.  This tree structure
/// allows the effects to have a a "time interval" that nests around
/// and within the time intervals of other effects.
#[derive(Debug)]
pub struct DCGTrace {
  /// The DCG effect (e.g., Alloc(MatchDiff), Dirty, Clean, etc.)
  pub effect:DCGEffect,

  /// The DCG edge on which this DCG effect takes place
  pub edge: DCGEdge,

  /// The DCG effects that occur subordinately as a result of this
  /// effect. (They begin after this effect begins, and the end before
  /// this effect ends).
  pub extent:DCGTraces,
}
/// A (boxed) vector of `DCGTrace`s.
pub type DCGTraces = Box<Vec<DCGTrace>>;
<commit_msg>better doc for dcg cleaning effects<commit_after>use engine::Name;
use macros::ProgPt;
use std::fmt::Debug;
//use std::hash::Hash;
use std::rc::Rc;
use std::collections::HashMap;

/// Reflected primitive data
pub trait Data : Debug { }

pub trait Reflect<T> : Debug {
  fn reflect (&self) -> T;
}

impl<S,T:Reflect<S>+Debug> Reflect<Option<S>> for Option<T> {
  fn reflect (&self) -> Option<S> {
    match *self {
      None => None,
      Some(ref x) => Some(x.reflect())
    }
  }
}

impl<'a,S,T:Reflect<S>+Debug> Reflect<S> for &'a Rc<T> {
  fn reflect (&self) -> S {
    (**self).reflect()
  }
}

impl<'a,S,T:Reflect<S>+Debug> Reflect<S> for Rc<T> {
  fn reflect (&self) -> S {
    (**self).reflect()
  }
}

/// Reflected value; Gives a syntax for inductive data type
/// constructors (`Constr`), named articulations (`Art`) and primitive
/// data (`Data).
#[derive(Debug,Clone)]
pub enum Val {
  /// Constructor, with value parameters.
  Constr(Name,Vec<Val>),
  /// Named articulation, and its content (an `Art` is either a named value, or a named computation).
  Art(Name,ArtContent),
  /// Primitive, immutable data.
  Data(Rc<Data>),

  /// Temporary; for marking places in code where we should produce a
  /// value, but don't yet have a good way to do so.
  ValTODO,
}

/// The content of an articulation: Either a cell holding a value, or
/// a thunk that has optionally produced a value.
#[derive(Debug,Clone)]
pub enum ArtContent {
  /// A cell holding a value
  Val(Rc<Val>),
  /// A thunk that, when forced, computes a value
  Comp(Option<Rc<Val>>),
}

/// `Reflected version of engine::Loc` A `Loc` is a particular
/// template for a `Name`: It is a path (a possibly-empty list of
/// `Name`s), followed by a distinguished `Name`.  A `Loc` can be
/// thought of roughly like a file path in UNIX (but Adapton has
/// nothing to do with files, or with UNIX, directly).
#[derive(PartialEq,Eq,Debug,Hash,Clone)]
pub struct Loc {
  /// The path of the `Loc` is a list of `Name`s.
  pub path: Path,
  /// The distinguished `Name` of the `Loc` (must be unique in the path).
  pub name: Name,
}

/// A `Path` here is just a `Vec` of `Name`s
pub type Path = Vec<Name>;

/// `Reflected version of engine::Effect`
#[derive(Debug,Clone)]
pub enum Effect {
  /// The effect consists of a thunk observing the value of another
  /// thunk or reference cell.  That is, the effect consists of
  /// **consuming** a value, by demanding its production.
  Force,
  /// The effect consists of a thunk allocating a value or thunk at a
  /// particular name.  That is, the effect consists of **producing**
  /// a value or computation.  If this content differs, then the
  /// allocation is a **reallocation**, and the engine dirties the old
  /// observers and allocators of the preceding content.
  Alloc,
}

/// Reflected version of `engine::Succ`
#[derive(Debug,Clone)]
pub struct Succ {
  /// Dirty invariant: If this edge is dirty, then all predecessors of
  /// the edge are dirty too.
  pub dirty:  bool,
  /// The target of the outgoing `Effect`
  pub loc:    Loc,
  /// The effect: either producing or consuming articulated content
  pub effect: Effect,
  /// The value either produced or consumed by this `Effect`
  pub value:  Val,
}

impl Reflect<Succ> for Succ {
  fn reflect (&self) -> Succ {
    self.clone()
  }
}

/// Reflected version of `engine::Pred`
#[derive(Debug)]
pub struct Pred {
  /// The predecessor of the node in question
  pub loc:    Loc,
  /// The effect that the predecessor has done to the node in question
  pub effect: Effect,
}

/// Reflected version of `engine::CompNode`
#[derive(Debug)]
pub struct CompNode {
  pub preds:   Vec<Pred>,
  pub succs:   Vec<Succ>,
  pub prog_pt: ProgPt,
  pub value:   Option<Val>,
}

/// Reflected version of `engine::MutNode`
#[derive(Debug)]
pub struct RefNode {
  pub preds: Vec<Pred>,
  pub value: Val,
}

/// Reflected version of `engine::PureNode`
#[derive(Debug)]
pub struct PureNode {
  pub value: Val,
}

/// Reflected version of `engine::GraphNode`
#[derive(Debug)]
pub enum GraphNode {
  Comp(CompNode),
  Ref(RefNode),
  Pure(PureNode),
}

/// Reflected version of `engine::Frame`
#[derive(Debug)]
pub struct Frame {
  pub loc:   Loc,
  pub succs: Vec<Succ>,
}

/// Reflected version of `engine::DCG`
#[derive(Debug)]
pub struct DCG {
  /// The current memo table, mapping `Loc`s to `GraphNode`s.

  pub table: HashMap<Loc, Box<GraphNode>>,
  pub stack: Vec<Frame>,
  pub path:  Vec<Name>,
}

/// Distinguish fresh allocations from those that reuse an existing location.
#[derive(Debug)]
pub enum DCGAlloc {
  /// The allocation was **created** fresh; it was **not** reused.
  LocFresh,
  /// The allocation matched the location of a prior allocation. its
  /// content may or may not also match.  The `bool` indicates the two
  /// cases: `true` means same content, `false` means changed content.
  LocExists,
}

/// When the program `force`s a computation, either the cache is
/// either empty (`CacheMiss`) or non-empty (`CacheHit`).  The cached
/// value may not be consistent without a cleaning.  When the program
/// `force`s a reference cell, it simply gets the current value.
#[derive(Debug)]
pub enum DCGForce {
  /// The DCG has no cached value for this computation; no prior
  /// computation will be reused.
  CompCacheMiss,
  /// The DCG has a cached value for this computation; it may not be
  /// consistent without a cleaning first.
  CompCacheHit,
  /// The forced node is a ref cell with a (mutable) value, and hence,
  /// no computation was necessary.  The `force` simply gets the
  /// current value.
  RefGet,
}

/// The effects of the DCG (including cleaning and dirtying) on one of
/// its edges.
#[derive(Debug)]
pub enum DCGEffect {
  /// Wrapper for Effect::Alloc; transition to DCG after the alloc.
  Alloc (DCGAlloc),

  /// Wrapper for Effect::Force; transition to DCG after the force.
  Force (DCGForce),

  /// Transition to this edge as **dirty** (potentially inconsistent).
  /// This transition may consist of marking other edges dirty.  The
  /// DCG's invariant about dirty edges is simple: If an edge is
  /// dirty, then all edges that force (demand/observe) the source of
  /// that edge must also be dirty.  This transitive closure property
  /// ensures that we do not accidentally reuse stale cached values by
  /// mistake (a dirty edge will always witness a potentially stale
  /// cached value).
  Dirty,

  /// Clean this edge, marking it **not dirty**, or equivalently,
  /// **definitely consistent**. Cleaning an edge consists of
  /// processing the edge's dirty transitive dependencies, if any.
  /// Recursively, this processing may consist of marking other edges
  /// clean (`CleanEdge`), and/or, removing edges (`Remove`) and
  /// replacing them via reevaluation under the current DCG state
  /// (`CleanEval`).
  ///
  /// This process finishes in one of two mutually-exclusive
  /// situations: Either the edge is cleaned, meaning that its target
  /// need not be recomputed (`CleanEdge`). Or else, the value on this
  /// edge has changed, and this means that the edge's source is
  /// potentially affected by the change. Consequently, this change
  /// requires that the edge source be reevaluated (`CleanEval`).
  CleanRec,

  /// Transition to this edge as **clean** (definitely consistent),
  /// after doing a recursive cleaning of its dependencies and finding
  /// that they are clean.  This effect is mutually-exclusive with
  /// `CleanEval`, and it occurs when `CleanEdge` **cannot** occur on
  /// an edge that is being recursively cleaned (via `CleanRec`).
  CleanEdge,

  /// Re-evaluate the previously-forced thunk that is the target of
  /// this edge, to clean it.  This effect is mutually-exclusive with
  /// `CleanEdge`.  It occurs when `CleanEdge` cannot occur.
  CleanEval,

  /// Transition to the DCG without this edge.  Perhaps it will be
  /// replaced via re-execution, sometime later.
  Remove,
}

/// An adge in the DCG, representing an effect of the incremental program.
#[derive(Debug)]
pub struct DCGEdge {
  /// The source of the directed edge; it is actively _doing_ the
  /// effect of `succ.effect` to `succ.loc`.  `None` means the doer is
  /// the **editor**, who is not identified by any location. (The editor
  /// is not a node in the DCG, but rather, an actor operating outside
  /// of it).
  pub loc: Option<Loc>,
  /// The effect and target of the directed edge.
  pub succ: Succ,
}

/// `DCGTrace`: A Rose-tree of DCG edge-effects.  This tree structure
/// allows the effects to have a a "time interval" that nests around
/// and within the time intervals of other effects.
#[derive(Debug)]
pub struct DCGTrace {
  /// The DCG effect (e.g., Alloc(MatchDiff), Dirty, Clean, etc.)
  pub effect:DCGEffect,

  /// The DCG edge on which this DCG effect takes place
  pub edge: DCGEdge,

  /// The DCG effects that occur subordinately as a result of this
  /// effect. (They begin after this effect begins, and the end before
  /// this effect ends).
  pub extent:DCGTraces,
}
/// A (boxed) vector of `DCGTrace`s.
pub type DCGTraces = Box<Vec<DCGTrace>>;
<|endoftext|>


<commit_before>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

use std;
use std::collections::HashMap;
use serde_json;
use serde::de::DeserializeOwned;

/// This enum represents the various types of HTTP requests.
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
pub enum Method {
    Get,
    Put,
    Post,
    Delete,
    NoImpl,
}

/// This enum represents the errors that might be encountered.
#[derive(Debug)]
pub enum RequestError {
    JsonStrError(serde_json::Error),
    StrCopyError(std::string::FromUtf8Error),
}

impl From<serde_json::Error> for RequestError {
    fn from(err: serde_json::Error) -> RequestError {
        RequestError::JsonStrError(err)
    }
}

impl From<std::string::FromUtf8Error> for RequestError {
    fn from(err: std::string::FromUtf8Error) -> RequestError {
        RequestError::StrCopyError(err)
    }
}

impl std::fmt::Display for RequestError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            RequestError::JsonStrError(err) => write!(f, "JSON error: {}", err),
            RequestError::StrCopyError(err) => write!(f, "UTF-8 error: {}", err),
        }
    }
}

impl std::error::Error for RequestError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            RequestError::JsonStrError(err) => Some(err),
            RequestError::StrCopyError(err) => Some(err),
        }
    }
}

/// A trait that allows for extracting variables from URIs.
pub trait FromUri {
    /// A function to parse a string into the correct type.
    fn from_uri(data: &str) -> Self;
}

impl FromUri for String {
    fn from_uri(data: &str) -> String {
        String::from(data)
    }
}

impl FromUri for i32 {
    fn from_uri(data: &str) -> i32 {
        data.parse::<i32>().expect("matched integer can't be parsed")
    }
}

impl FromUri for u32 {
    fn from_uri(data: &str) -> u32 {
        data.parse::<u32>().expect("matched integer can't be parsed")
    }
}

impl FromUri for f32 {
    fn from_uri(data: &str) -> f32 {
        data.parse::<f32>().expect("matched float can't be parsed")
    }
}

/// This struct represents a request from an HTTP client.
#[derive(Debug)]
pub struct Request {
    pub method:  Method,
    pub path:    String,
    pub payload: Vec<u8>,
    pub params:  HashMap<String, String>,
    headers:     HashMap<String, String>,
}

impl Request {
    /// Create a new, empty Request.
    pub fn new() -> Request {
        Request {
            method:  Method::NoImpl,
            path:    String::new(),
            headers: HashMap::new(),
            params:  HashMap::new(),
            payload: Vec::with_capacity(2048),
        }
    }

    /// Get an HTTP header contained in the Request.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let browser = req.get_header("User-Agent");
    ///
    ///     match browser {
    ///         Some(ua) => utils::make_response(format!("You're using {}!", ua), "text/plain", 200),
    ///         None     => utils::make_response("Bad browser, no user agent!", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_header(&self, name: &str) -> Option<String> {
        let key = String::from(name);

        match self.headers.get(&key) {
            Some(val)   => Some(val.clone()),
            None        => None,
        }
    }

    /// Get a variable from the URI.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the route "/hello/<str:name>"
    /// fn handler(req: &Request) -> Response {
    ///     let name: String = req.get("name");
    ///     utils::make_response(format!("<b>Hello, {}!</b>", name), "text/html", 200)
    /// }
    /// ```
    pub fn get<T: FromUri>(&self, name: &str) -> T {
        if !self.params.contains_key(name) {
            panic!("invalid route parameter {:?}", name);
        }

        FromUri::from_uri(&self.params[name])
    }

    /// Get a raw JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data = req.get_json();
    ///
    ///     match data {
    ///         Ok(val) => utils::make_response(format!("We got: {}", val), "text/plain", 200),
    ///         Err(_)  => utils::make_response("We got nothing :(", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_json(&self) -> Result<serde_json::Value, RequestError> {
        let payload = String::from_utf8(self.payload.clone())?;
        let data = serde_json::from_str(&payload)?;

        Ok(data)
    }

    /// Get a composed JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// use canteen::{Request, Response};
    ///
    /// #[derive(RustcDecodable)]
    /// struct Foo {
    ///     item: i32,
    /// }
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data: Foo = req.get_json_obj();
    ///
    ///     match data {
    ///         Ok(foo) => utils::make_response(format!("We got: {}!", data.item), "text/plain", 200),
    ///         Err(_)  => utils::make_response("We got nothing :(", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_json_obj<T>(&self) -> Result<T, RequestError>
                where T: DeserializeOwned {
        let payload = String::from_utf8(self.payload.clone())?;
        let data = serde_json::from_str(&payload)?;

        Ok(data)
    }

    fn parse(&mut self, rqstr: &str) {
        let mut buf: Vec<&str> = rqstr.splitn(2, "\r\n").collect();
        let ask: Vec<&str> = buf[0].splitn(3, ' ').collect();

        self.method = match ask[0] {
            "GET"           => Method::Get,
            "PUT" | "PATCH" => Method::Put,
            "POST"          => Method::Post,
            "DELETE"        => Method::Delete,
            _               => Method::NoImpl,
        };
        self.path = String::from(ask[1]);

        loop {
            buf = buf[1].splitn(2, "\r\n").collect();

            if buf[0] == "" {
                if buf.len() == 1 || buf[1] == "" {
                    // no payload
                    break;
                }

                self.payload.extend(buf[1].as_bytes());
                break;
            }

            let hdr: Vec<&str> = buf[0].splitn(2, ": ").collect();

            if hdr.len() == 2 {
                self.headers.insert(String::from(hdr[0]), String::from(hdr[1]));
            }
        }
    }
}

impl Default for Request {
    fn default() -> Self {
        Self::new()
    }
}

impl std::str::FromStr for Request {
    type Err = RequestError;

    /// Create a Request from an HTTP request string.
    fn from_str(rqstr: &str) -> Result<Self, Self::Err> {
        let mut req = Request::new();
        req.parse(rqstr);
        Ok(req)
    }
}

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

    #[derive(Deserialize)]
    struct Foo {
        item: i32,
    }

    #[test]
    fn test_fromuri_trait_i32() {
        let pos = String::from("1234");
        assert_eq!(1234, <i32 as FromUri>::from_uri(&pos));

        let neg = String::from("-4321");
        assert_eq!(-4321, <i32 as FromUri>::from_uri(&neg));
    }

    #[test]
    fn test_fromuri_trait_u32() {
        let orig = String::from("1234");
        assert_eq!(1234, <u32 as FromUri>::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_string() {
        let orig = String::from("foobar");
        assert_eq!("foobar", <String as FromUri>::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_float() {
        let pos = String::from("123.45");
        assert_eq!(123.45f32, <f32 as FromUri>::from_uri(&pos));

        let neg = String::from("-54.321");
        assert_eq!(-54.321f32, <f32 as FromUri>::from_uri(&neg));
    }

    #[test]
    fn test_get_fromuri_i32() {
        let mut req = Request::new();
        req.params.insert(String::from("test"), String::from("1234"));
        let val: i32 = req.get("test");

        assert_eq!(1234, val);
    }

    #[test]
    fn test_get_json() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data = req.get_json().unwrap();

        assert_eq!(true, data.is_object());

        let obj = data.as_object().unwrap();
        let val = obj.get("item").unwrap();

        assert_eq!(true, val.is_u64());
        assert_eq!(123u64, val.as_u64().unwrap());
    }

    #[test]
    fn test_get_json_obj() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data: Foo = req.get_json_obj().unwrap();

        assert_eq!(123, data.item);
    }
}
<commit_msg>this shoud fix #10 lowercase header keys<commit_after>// Copyright (c) 2016
// Jeff Nettleton
//
// Licensed under the MIT license (http://opensource.org/licenses/MIT). This
// file may not be copied, modified, or distributed except according to those
// terms

use std;
use std::collections::HashMap;
use serde_json;
use serde::de::DeserializeOwned;

/// This enum represents the various types of HTTP requests.
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
pub enum Method {
    Get,
    Put,
    Post,
    Delete,
    NoImpl,
}

/// This enum represents the errors that might be encountered.
#[derive(Debug)]
pub enum RequestError {
    JsonStrError(serde_json::Error),
    StrCopyError(std::string::FromUtf8Error),
}

impl From<serde_json::Error> for RequestError {
    fn from(err: serde_json::Error) -> RequestError {
        RequestError::JsonStrError(err)
    }
}

impl From<std::string::FromUtf8Error> for RequestError {
    fn from(err: std::string::FromUtf8Error) -> RequestError {
        RequestError::StrCopyError(err)
    }
}

impl std::fmt::Display for RequestError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            RequestError::JsonStrError(err) => write!(f, "JSON error: {}", err),
            RequestError::StrCopyError(err) => write!(f, "UTF-8 error: {}", err),
        }
    }
}

impl std::error::Error for RequestError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            RequestError::JsonStrError(err) => Some(err),
            RequestError::StrCopyError(err) => Some(err),
        }
    }
}

/// A trait that allows for extracting variables from URIs.
pub trait FromUri {
    /// A function to parse a string into the correct type.
    fn from_uri(data: &str) -> Self;
}

impl FromUri for String {
    fn from_uri(data: &str) -> String {
        String::from(data)
    }
}

impl FromUri for i32 {
    fn from_uri(data: &str) -> i32 {
        data.parse::<i32>().expect("matched integer can't be parsed")
    }
}

impl FromUri for u32 {
    fn from_uri(data: &str) -> u32 {
        data.parse::<u32>().expect("matched integer can't be parsed")
    }
}

impl FromUri for f32 {
    fn from_uri(data: &str) -> f32 {
        data.parse::<f32>().expect("matched float can't be parsed")
    }
}

/// This struct represents a request from an HTTP client.
#[derive(Debug)]
pub struct Request {
    pub method:  Method,
    pub path:    String,
    pub payload: Vec<u8>,
    pub params:  HashMap<String, String>,
    headers:     HashMap<String, String>,
}

impl Request {
    /// Create a new, empty Request.
    pub fn new() -> Request {
        Request {
            method:  Method::NoImpl,
            path:    String::new(),
            headers: HashMap::new(),
            params:  HashMap::new(),
            payload: Vec::with_capacity(2048),
        }
    }

    /// Get an HTTP header contained in the Request.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let browser = req.get_header("User-Agent");
    ///
    ///     match browser {
    ///         Some(ua) => utils::make_response(format!("You're using {}!", ua), "text/plain", 200),
    ///         None     => utils::make_response("Bad browser, no user agent!", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_header(&self, name: &str) -> Option<String> {
        let key = String::from(name.to_lowercase());

        match self.headers.get(&key) {
            Some(val)   => Some(val.clone()),
            None        => None,
        }
    }

    /// Get a variable from the URI.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the route "/hello/<str:name>"
    /// fn handler(req: &Request) -> Response {
    ///     let name: String = req.get("name");
    ///     utils::make_response(format!("<b>Hello, {}!</b>", name), "text/html", 200)
    /// }
    /// ```
    pub fn get<T: FromUri>(&self, name: &str) -> T {
        if !self.params.contains_key(name) {
            panic!("invalid route parameter {:?}", name);
        }

        FromUri::from_uri(&self.params[name])
    }

    /// Get a raw JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use canteen::{Request, Response};
    /// use canteen::utils;
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data = req.get_json();
    ///
    ///     match data {
    ///         Ok(val) => utils::make_response(format!("We got: {}", val), "text/plain", 200),
    ///         Err(_)  => utils::make_response("We got nothing :(", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_json(&self) -> Result<serde_json::Value, RequestError> {
        let payload = String::from_utf8(self.payload.clone())?;
        let data = serde_json::from_str(&payload)?;

        Ok(data)
    }

    /// Get a composed JSON payload from the request.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// use canteen::{Request, Response};
    ///
    /// #[derive(RustcDecodable)]
    /// struct Foo {
    ///     item: i32,
    /// }
    ///
    /// // Given the POST route "/hello"
    /// fn handler(req: &Request) -> Response {
    ///     let data: Foo = req.get_json_obj();
    ///
    ///     match data {
    ///         Ok(foo) => utils::make_response(format!("We got: {}!", data.item), "text/plain", 200),
    ///         Err(_)  => utils::make_response("We got nothing :(", "text/plain", 200),
    ///     }
    /// }
    /// ```
    pub fn get_json_obj<T>(&self) -> Result<T, RequestError>
                where T: DeserializeOwned {
        let payload = String::from_utf8(self.payload.clone())?;
        let data = serde_json::from_str(&payload)?;

        Ok(data)
    }

    fn parse(&mut self, rqstr: &str) {
        let mut buf: Vec<&str> = rqstr.splitn(2, "\r\n").collect();
        let ask: Vec<&str> = buf[0].splitn(3, ' ').collect();

        self.method = match ask[0] {
            "GET"           => Method::Get,
            "PUT" | "PATCH" => Method::Put,
            "POST"          => Method::Post,
            "DELETE"        => Method::Delete,
            _               => Method::NoImpl,
        };
        self.path = String::from(ask[1]);

        loop {
            buf = buf[1].splitn(2, "\r\n").collect();

            if buf[0] == "" {
                if buf.len() == 1 || buf[1] == "" {
                    // no payload
                    break;
                }

                self.payload.extend(buf[1].as_bytes());
                break;
            }

            let hdr: Vec<&str> = buf[0].splitn(2, ": ").collect();

            if hdr.len() == 2 {
                self.headers.insert(String::from(hdr[0].to_lowercase()), String::from(hdr[1]));
            }
        }
    }
}

impl Default for Request {
    fn default() -> Self {
        Self::new()
    }
}

impl std::str::FromStr for Request {
    type Err = RequestError;

    /// Create a Request from an HTTP request string.
    fn from_str(rqstr: &str) -> Result<Self, Self::Err> {
        let mut req = Request::new();
        req.parse(rqstr);
        Ok(req)
    }
}

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

    #[derive(Deserialize)]
    struct Foo {
        item: i32,
    }

    #[test]
    fn test_fromuri_trait_i32() {
        let pos = String::from("1234");
        assert_eq!(1234, <i32 as FromUri>::from_uri(&pos));

        let neg = String::from("-4321");
        assert_eq!(-4321, <i32 as FromUri>::from_uri(&neg));
    }

    #[test]
    fn test_fromuri_trait_u32() {
        let orig = String::from("1234");
        assert_eq!(1234, <u32 as FromUri>::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_string() {
        let orig = String::from("foobar");
        assert_eq!("foobar", <String as FromUri>::from_uri(&orig));
    }

    #[test]
    fn test_fromuri_trait_float() {
        let pos = String::from("123.45");
        assert_eq!(123.45f32, <f32 as FromUri>::from_uri(&pos));

        let neg = String::from("-54.321");
        assert_eq!(-54.321f32, <f32 as FromUri>::from_uri(&neg));
    }

    #[test]
    fn test_get_fromuri_i32() {
        let mut req = Request::new();
        req.params.insert(String::from("test"), String::from("1234"));
        let val: i32 = req.get("test");

        assert_eq!(1234, val);
    }

    #[test]
    fn test_get_json() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data = req.get_json().unwrap();

        assert_eq!(true, data.is_object());

        let obj = data.as_object().unwrap();
        let val = obj.get("item").unwrap();

        assert_eq!(true, val.is_u64());
        assert_eq!(123u64, val.as_u64().unwrap());
    }

    #[test]
    fn test_get_json_obj() {
        let mut req = Request::new();
        req.payload.extend_from_slice("{ \"item\": 123 }".as_bytes());

        let data: Foo = req.get_json_obj().unwrap();

        assert_eq!(123, data.item);
    }
}
<|endoftext|>