<commit_before>use assert_matches::assert_matches;
use js_int::{int, uint};
use ruma_common::{
    event_id,
    events::{MessageLikeEvent, StateEvent, SyncMessageLikeEvent, SyncStateEvent},
    room_alias_id, room_id,
    serde::test::serde_json_eq,
    user_id,
};
use serde_json::{from_value as from_json_value, json, Value as JsonValue};

use ruma_common::{
    events::{
        room::{
            aliases::RoomAliasesEventContent,
            message::{MessageType, RoomMessageEventContent},
            power_levels::RoomPowerLevelsEventContent,
        },
        AnyEphemeralRoomEvent, AnyMessageLikeEvent, AnyStateEvent, AnySyncMessageLikeEvent,
        AnySyncStateEvent, AnySyncTimelineEvent, AnyTimelineEvent, EphemeralRoomEventType,
        GlobalAccountDataEventType, MessageLikeEventType, MessageLikeUnsigned,
        OriginalMessageLikeEvent, OriginalStateEvent, OriginalSyncMessageLikeEvent,
        OriginalSyncStateEvent, RoomAccountDataEventType, StateEventType, ToDeviceEventType,
    },
    MilliSecondsSinceUnixEpoch,
};

fn message_event() -> JsonValue {
    json!({
        "content": {
            "body": "baba",
            "format": "org.matrix.custom.html",
            "formatted_body": "baba",
            "msgtype": "m.text"
        },
        "event_id": "$152037280074GZeOm:localhost",
        "origin_server_ts": 1,
        "sender": "@example:localhost",
        "room_id": "!room:room.com",
        "type": "m.room.message",
        "unsigned": {
            "age": 1
        }
    })
}

fn message_event_sync() -> JsonValue {
    json!({
        "content": {
            "body": "baba",
            "format": "org.matrix.custom.html",
            "formatted_body": "baba",
            "msgtype": "m.text"
        },
        "event_id": "$152037280074GZeOm:localhost",
        "origin_server_ts": 1,
        "sender": "@example:localhost",
        "type": "m.room.message",
        "unsigned": {
            "age": 1
        }
    })
}

fn aliases_event() -> JsonValue {
    json!({
        "content": {
            "aliases": ["#somewhere:localhost"]
        },
        "event_id": "$152037280074GZeOm:localhost",
        "origin_server_ts": 1,
        "sender": "@example:localhost",
        "state_key": "room.com",
        "room_id": "!room:room.com",
        "type": "m.room.aliases",
        "unsigned": {
            "age": 1
        }
    })
}

fn aliases_event_sync() -> JsonValue {
    json!({
        "content": {
            "aliases": ["#somewhere:localhost"]
        },
        "event_id": "$152037280074GZeOm:localhost",
        "origin_server_ts": 1,
        "sender": "@example:localhost",
        "state_key": "example.com",
        "type": "m.room.aliases",
        "unsigned": {
            "age": 1
        }
    })
}

#[test]
fn power_event_sync_deserialization() {
    let json_data = json!({
        "content": {
            "ban": 50,
            "events": {
                "m.room.avatar": 50,
                "m.room.canonical_alias": 50,
                "m.room.history_visibility": 100,
                "m.room.name": 50,
                "m.room.power_levels": 100
            },
            "events_default": 0,
            "invite": 0,
            "kick": 50,
            "redact": 50,
            "state_default": 50,
            "users": {
                "@example:localhost": 100
            },
            "users_default": 0
        },
        "event_id": "$15139375512JaHAW:localhost",
        "origin_server_ts": 45,
        "sender": "@example:localhost",
        "state_key": "",
        "type": "m.room.power_levels",
        "unsigned": {
            "age": 45
        }
    });

    let ban = assert_matches!(
        from_json_value::<AnySyncTimelineEvent>(json_data),
        Ok(AnySyncTimelineEvent::State(
            AnySyncStateEvent::RoomPowerLevels(SyncStateEvent::Original(
                OriginalSyncStateEvent {
                    content: RoomPowerLevelsEventContent {
                        ban, ..
                    },
                    ..
                },
            )),
        )) => ban
    );
    assert_eq!(ban, int!(50));
}

#[test]
fn message_event_sync_deserialization() {
    let json_data = message_event_sync();

    let text_content = assert_matches!(
        from_json_value::<AnySyncTimelineEvent>(json_data),
        Ok(AnySyncTimelineEvent::MessageLike(
            AnySyncMessageLikeEvent::RoomMessage(SyncMessageLikeEvent::Original(
                OriginalSyncMessageLikeEvent {
                    content: RoomMessageEventContent {
                        msgtype: MessageType::Text(text_content),
                        ..
                    },
                    ..
                },
            ))
        )) => text_content
    );
    assert_eq!(text_content.body, "baba");
    let formatted = text_content.formatted.unwrap();
    assert_eq!(formatted.body, "baba");
}

#[test]
fn aliases_event_sync_deserialization() {
    let json_data = aliases_event_sync();

    let ev = assert_matches!(
        from_json_value::<AnySyncTimelineEvent>(json_data),
        Ok(AnySyncTimelineEvent::State(AnySyncStateEvent::RoomAliases(SyncStateEvent::Original(
            ev,
        )))) => ev
    );

    assert_eq!(ev.content.aliases, vec![room_alias_id!("#somewhere:localhost")]);
}

#[test]
fn message_room_event_deserialization() {
    let json_data = message_event();

    let text_content = assert_matches!(
        from_json_value::<AnyTimelineEvent>(json_data),
        Ok(AnyTimelineEvent::MessageLike(
            AnyMessageLikeEvent::RoomMessage(MessageLikeEvent::Original(
                OriginalMessageLikeEvent {
                    content: RoomMessageEventContent {
                        msgtype: MessageType::Text(text_content),
                        ..
                    },
                    ..
                },
            ))
        )) => text_content
    );
    assert_eq!(text_content.body, "baba");
    let formatted = text_content.formatted.unwrap();
    assert_eq!(formatted.body, "baba");
}

#[test]
fn message_event_serialization() {
    let event = OriginalMessageLikeEvent {
        content: RoomMessageEventContent::text_plain("test"),
        event_id: event_id!("$1234:example.com").to_owned(),
        origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(0)),
        room_id: room_id!("!roomid:example.com").to_owned(),
        sender: user_id!("@test:example.com").to_owned(),
        unsigned: MessageLikeUnsigned::default(),
    };

    #[cfg(not(feature = "unstable-msc1767"))]
    assert_eq!(
        serde_json::to_string(&event).expect("Failed to serialize message event"),
        r#"{"type":"m.room.message","content":{"msgtype":"m.text","body":"test"},"event_id":"$1234:example.com","sender":"@test:example.com","origin_server_ts":0,"room_id":"!roomid:example.com"}"#
    );

    #[cfg(feature = "unstable-msc1767")]
    assert_eq!(
        serde_json::to_string(&event).expect("Failed to serialize message event"),
        r#"{"type":"m.room.message","content":{"msgtype":"m.text","body":"test","org.matrix.msc1767.text":"test"},"event_id":"$1234:example.com","sender":"@test:example.com","origin_server_ts":0,"room_id":"!roomid:example.com"}"#
    );
}

#[test]
fn alias_room_event_deserialization() {
    let json_data = aliases_event();

    let aliases = assert_matches!(
        from_json_value::<AnyTimelineEvent>(json_data),
        Ok(AnyTimelineEvent::State(
            AnyStateEvent::RoomAliases(StateEvent::Original(OriginalStateEvent {
                content: RoomAliasesEventContent {
                    aliases,
                    ..
                },
                ..
            }))
        )) => aliases
    );
    assert_eq!(aliases, vec![room_alias_id!("#somewhere:localhost")]);
}

#[test]
fn message_event_deserialization() {
    let json_data = message_event();

    let text_content = assert_matches!(
        from_json_value::<AnyTimelineEvent>(json_data),
        Ok(AnyTimelineEvent::MessageLike(
            AnyMessageLikeEvent::RoomMessage(MessageLikeEvent::Original(OriginalMessageLikeEvent {
                content: RoomMessageEventContent {
                    msgtype: MessageType::Text(text_content),
                    ..
                },
                ..
            }))
        )) => text_content
    );
    assert_eq!(text_content.body, "baba");
    let formatted = text_content.formatted.unwrap();
    assert_eq!(formatted.body, "baba");
}

#[test]
fn alias_event_deserialization() {
    let json_data = aliases_event();

    let aliases = assert_matches!(
        from_json_value::<AnyTimelineEvent>(json_data),
        Ok(AnyTimelineEvent::State(
            AnyStateEvent::RoomAliases(StateEvent::Original(OriginalStateEvent {
                content: RoomAliasesEventContent {
                    aliases,
                    ..
                },
                ..
            }))
        )) => aliases
    );
    assert_eq!(aliases, vec![room_alias_id!("#somewhere:localhost")]);
}

#[test]
fn alias_event_field_access() {
    let json_data = aliases_event();

    let state_event = assert_matches!(
        from_json_value::<AnyTimelineEvent>(json_data.clone()),
        Ok(AnyTimelineEvent::State(state_event)) => state_event
    );
    assert_eq!(state_event.state_key(), "room.com");
    assert_eq!(state_event.room_id(), "!room:room.com");
    assert_eq!(state_event.event_id(), "$152037280074GZeOm:localhost");
    assert_eq!(state_event.sender(), "@example:localhost");

    let deser = from_json_value::<AnyStateEvent>(json_data).unwrap();
    let ev = assert_matches!(&deser, AnyStateEvent::RoomAliases(StateEvent::Original(ev)) => ev);
    assert_eq!(ev.content.aliases, vec![room_alias_id!("#somewhere:localhost")]);
    assert_eq!(deser.event_type().to_string(), "m.room.aliases");
}

#[test]
fn ephemeral_event_deserialization() {
    let json_data = json!({
        "content": {
            "user_ids": [
                "@alice:matrix.org",
                "@bob:example.com"
            ]
        },
        "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
        "type": "m.typing"
    });

    let ephem = assert_matches!(
        from_json_value::<AnyEphemeralRoomEvent>(json_data),
        Ok(ephem @ AnyEphemeralRoomEvent::Typing(_)) => ephem
    );
    assert_eq!(ephem.room_id(), "!jEsUZKDJdhlrceRyVU:example.org");
}

#[test]
#[allow(deprecated)]
fn serialize_and_deserialize_from_display_form() {
    use ruma_common::events::EventType;

    serde_json_eq(EventType::CallAnswer, json!("m.call.answer"));
    serde_json_eq(MessageLikeEventType::CallAnswer, json!("m.call.answer"));
    serde_json_eq(EventType::CallCandidates, json!("m.call.candidates"));
    serde_json_eq(EventType::CallHangup, json!("m.call.hangup"));
    serde_json_eq(EventType::CallInvite, json!("m.call.invite"));
    serde_json_eq(EventType::Direct, json!("m.direct"));
    serde_json_eq(GlobalAccountDataEventType::Direct, json!("m.direct"));
    serde_json_eq(EventType::Dummy, json!("m.dummy"));
    serde_json_eq(EventType::ForwardedRoomKey, json!("m.forwarded_room_key"));
    serde_json_eq(EventType::FullyRead, json!("m.fully_read"));
    serde_json_eq(RoomAccountDataEventType::FullyRead, json!("m.fully_read"));
    serde_json_eq(EventType::KeyVerificationAccept, json!("m.key.verification.accept"));
    serde_json_eq(EventType::KeyVerificationCancel, json!("m.key.verification.cancel"));
    serde_json_eq(EventType::KeyVerificationDone, json!("m.key.verification.done"));
    serde_json_eq(EventType::KeyVerificationKey, json!("m.key.verification.key"));
    serde_json_eq(ToDeviceEventType::KeyVerificationKey, json!("m.key.verification.key"));
    serde_json_eq(EventType::KeyVerificationMac, json!("m.key.verification.mac"));
    serde_json_eq(EventType::KeyVerificationReady, json!("m.key.verification.ready"));
    serde_json_eq(EventType::KeyVerificationRequest, json!("m.key.verification.request"));
    serde_json_eq(EventType::KeyVerificationStart, json!("m.key.verification.start"));
    serde_json_eq(EventType::IgnoredUserList, json!("m.ignored_user_list"));
    serde_json_eq(EventType::PolicyRuleRoom, json!("m.policy.rule.room"));
    serde_json_eq(EventType::PolicyRuleServer, json!("m.policy.rule.server"));
    serde_json_eq(EventType::PolicyRuleUser, json!("m.policy.rule.user"));
    serde_json_eq(EventType::Presence, json!("m.presence"));
    serde_json_eq(EventType::PushRules, json!("m.push_rules"));
    serde_json_eq(EventType::Receipt, json!("m.receipt"));
    serde_json_eq(EventType::RoomAliases, json!("m.room.aliases"));
    serde_json_eq(EventType::RoomAvatar, json!("m.room.avatar"));
    serde_json_eq(EventType::RoomCanonicalAlias, json!("m.room.canonical_alias"));
    serde_json_eq(EventType::RoomCreate, json!("m.room.create"));
    serde_json_eq(StateEventType::RoomCreate, json!("m.room.create"));
    serde_json_eq(EventType::RoomEncrypted, json!("m.room.encrypted"));
    serde_json_eq(EventType::RoomEncryption, json!("m.room.encryption"));
    serde_json_eq(EventType::RoomGuestAccess, json!("m.room.guest_access"));
    serde_json_eq(EventType::RoomHistoryVisibility, json!("m.room.history_visibility"));
    serde_json_eq(EventType::RoomJoinRules, json!("m.room.join_rules"));
    serde_json_eq(EventType::RoomMember, json!("m.room.member"));
    serde_json_eq(EventType::RoomMessage, json!("m.room.message"));
    serde_json_eq(EventType::RoomName, json!("m.room.name"));
    serde_json_eq(EventType::RoomPinnedEvents, json!("m.room.pinned_events"));
    serde_json_eq(EventType::RoomPowerLevels, json!("m.room.power_levels"));
    serde_json_eq(EventType::RoomRedaction, json!("m.room.redaction"));
    serde_json_eq(EventType::RoomServerAcl, json!("m.room.server_acl"));
    serde_json_eq(EventType::RoomThirdPartyInvite, json!("m.room.third_party_invite"));
    serde_json_eq(EventType::RoomTombstone, json!("m.room.tombstone"));
    serde_json_eq(EventType::RoomTopic, json!("m.room.topic"));
    serde_json_eq(EventType::RoomKey, json!("m.room_key"));
    serde_json_eq(EventType::RoomKeyRequest, json!("m.room_key_request"));
    serde_json_eq(EventType::Sticker, json!("m.sticker"));
    serde_json_eq(EventType::Tag, json!("m.tag"));
    serde_json_eq(EventType::Typing, json!("m.typing"));
    serde_json_eq(EphemeralRoomEventType::Typing, json!("m.typing"));
}
<commit_msg>events: Simplify serialize_and_deserialize_from_display_form test<commit_after>use assert_matches::assert_matches;
use js_int::{int, uint};
use ruma_common::{
    event_id,
    events::{MessageLikeEvent, StateEvent, SyncMessageLikeEvent, SyncStateEvent},
    room_alias_id, room_id,
    serde::test::serde_json_eq,
    user_id,
};
use serde_json::{from_value as from_json_value, json, Value as JsonValue};

use ruma_common::{
    events::{
        room::{
            aliases::RoomAliasesEventContent,
            message::{MessageType, RoomMessageEventContent},
            power_levels::RoomPowerLevelsEventContent,
        },
        AnyEphemeralRoomEvent, AnyMessageLikeEvent, AnyStateEvent, AnySyncMessageLikeEvent,
        AnySyncStateEvent, AnySyncTimelineEvent, AnyTimelineEvent, EphemeralRoomEventType,
        GlobalAccountDataEventType, MessageLikeEventType, MessageLikeUnsigned,
        OriginalMessageLikeEvent, OriginalStateEvent, OriginalSyncMessageLikeEvent,
        OriginalSyncStateEvent, RoomAccountDataEventType, StateEventType, ToDeviceEventType,
    },
    MilliSecondsSinceUnixEpoch,
};

fn message_event() -> JsonValue {
    json!({
        "content": {
            "body": "baba",
            "format": "org.matrix.custom.html",
            "formatted_body": "baba",
            "msgtype": "m.text"
        },
        "event_id": "$152037280074GZeOm:localhost",
        "origin_server_ts": 1,
        "sender": "@example:localhost",
        "room_id": "!room:room.com",
        "type": "m.room.message",
        "unsigned": {
            "age": 1
        }
    })
}

fn message_event_sync() -> JsonValue {
    json!({
        "content": {
            "body": "baba",
            "format": "org.matrix.custom.html",
            "formatted_body": "baba",
            "msgtype": "m.text"
        },
        "event_id": "$152037280074GZeOm:localhost",
        "origin_server_ts": 1,
        "sender": "@example:localhost",
        "type": "m.room.message",
        "unsigned": {
            "age": 1
        }
    })
}

fn aliases_event() -> JsonValue {
    json!({
        "content": {
            "aliases": ["#somewhere:localhost"]
        },
        "event_id": "$152037280074GZeOm:localhost",
        "origin_server_ts": 1,
        "sender": "@example:localhost",
        "state_key": "room.com",
        "room_id": "!room:room.com",
        "type": "m.room.aliases",
        "unsigned": {
            "age": 1
        }
    })
}

fn aliases_event_sync() -> JsonValue {
    json!({
        "content": {
            "aliases": ["#somewhere:localhost"]
        },
        "event_id": "$152037280074GZeOm:localhost",
        "origin_server_ts": 1,
        "sender": "@example:localhost",
        "state_key": "example.com",
        "type": "m.room.aliases",
        "unsigned": {
            "age": 1
        }
    })
}

#[test]
fn power_event_sync_deserialization() {
    let json_data = json!({
        "content": {
            "ban": 50,
            "events": {
                "m.room.avatar": 50,
                "m.room.canonical_alias": 50,
                "m.room.history_visibility": 100,
                "m.room.name": 50,
                "m.room.power_levels": 100
            },
            "events_default": 0,
            "invite": 0,
            "kick": 50,
            "redact": 50,
            "state_default": 50,
            "users": {
                "@example:localhost": 100
            },
            "users_default": 0
        },
        "event_id": "$15139375512JaHAW:localhost",
        "origin_server_ts": 45,
        "sender": "@example:localhost",
        "state_key": "",
        "type": "m.room.power_levels",
        "unsigned": {
            "age": 45
        }
    });

    let ban = assert_matches!(
        from_json_value::<AnySyncTimelineEvent>(json_data),
        Ok(AnySyncTimelineEvent::State(
            AnySyncStateEvent::RoomPowerLevels(SyncStateEvent::Original(
                OriginalSyncStateEvent {
                    content: RoomPowerLevelsEventContent {
                        ban, ..
                    },
                    ..
                },
            )),
        )) => ban
    );
    assert_eq!(ban, int!(50));
}

#[test]
fn message_event_sync_deserialization() {
    let json_data = message_event_sync();

    let text_content = assert_matches!(
        from_json_value::<AnySyncTimelineEvent>(json_data),
        Ok(AnySyncTimelineEvent::MessageLike(
            AnySyncMessageLikeEvent::RoomMessage(SyncMessageLikeEvent::Original(
                OriginalSyncMessageLikeEvent {
                    content: RoomMessageEventContent {
                        msgtype: MessageType::Text(text_content),
                        ..
                    },
                    ..
                },
            ))
        )) => text_content
    );
    assert_eq!(text_content.body, "baba");
    let formatted = text_content.formatted.unwrap();
    assert_eq!(formatted.body, "baba");
}

#[test]
fn aliases_event_sync_deserialization() {
    let json_data = aliases_event_sync();

    let ev = assert_matches!(
        from_json_value::<AnySyncTimelineEvent>(json_data),
        Ok(AnySyncTimelineEvent::State(AnySyncStateEvent::RoomAliases(SyncStateEvent::Original(
            ev,
        )))) => ev
    );

    assert_eq!(ev.content.aliases, vec![room_alias_id!("#somewhere:localhost")]);
}

#[test]
fn message_room_event_deserialization() {
    let json_data = message_event();

    let text_content = assert_matches!(
        from_json_value::<AnyTimelineEvent>(json_data),
        Ok(AnyTimelineEvent::MessageLike(
            AnyMessageLikeEvent::RoomMessage(MessageLikeEvent::Original(
                OriginalMessageLikeEvent {
                    content: RoomMessageEventContent {
                        msgtype: MessageType::Text(text_content),
                        ..
                    },
                    ..
                },
            ))
        )) => text_content
    );
    assert_eq!(text_content.body, "baba");
    let formatted = text_content.formatted.unwrap();
    assert_eq!(formatted.body, "baba");
}

#[test]
fn message_event_serialization() {
    let event = OriginalMessageLikeEvent {
        content: RoomMessageEventContent::text_plain("test"),
        event_id: event_id!("$1234:example.com").to_owned(),
        origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(0)),
        room_id: room_id!("!roomid:example.com").to_owned(),
        sender: user_id!("@test:example.com").to_owned(),
        unsigned: MessageLikeUnsigned::default(),
    };

    #[cfg(not(feature = "unstable-msc1767"))]
    assert_eq!(
        serde_json::to_string(&event).expect("Failed to serialize message event"),
        r#"{"type":"m.room.message","content":{"msgtype":"m.text","body":"test"},"event_id":"$1234:example.com","sender":"@test:example.com","origin_server_ts":0,"room_id":"!roomid:example.com"}"#
    );

    #[cfg(feature = "unstable-msc1767")]
    assert_eq!(
        serde_json::to_string(&event).expect("Failed to serialize message event"),
        r#"{"type":"m.room.message","content":{"msgtype":"m.text","body":"test","org.matrix.msc1767.text":"test"},"event_id":"$1234:example.com","sender":"@test:example.com","origin_server_ts":0,"room_id":"!roomid:example.com"}"#
    );
}

#[test]
fn alias_room_event_deserialization() {
    let json_data = aliases_event();

    let aliases = assert_matches!(
        from_json_value::<AnyTimelineEvent>(json_data),
        Ok(AnyTimelineEvent::State(
            AnyStateEvent::RoomAliases(StateEvent::Original(OriginalStateEvent {
                content: RoomAliasesEventContent {
                    aliases,
                    ..
                },
                ..
            }))
        )) => aliases
    );
    assert_eq!(aliases, vec![room_alias_id!("#somewhere:localhost")]);
}

#[test]
fn message_event_deserialization() {
    let json_data = message_event();

    let text_content = assert_matches!(
        from_json_value::<AnyTimelineEvent>(json_data),
        Ok(AnyTimelineEvent::MessageLike(
            AnyMessageLikeEvent::RoomMessage(MessageLikeEvent::Original(OriginalMessageLikeEvent {
                content: RoomMessageEventContent {
                    msgtype: MessageType::Text(text_content),
                    ..
                },
                ..
            }))
        )) => text_content
    );
    assert_eq!(text_content.body, "baba");
    let formatted = text_content.formatted.unwrap();
    assert_eq!(formatted.body, "baba");
}

#[test]
fn alias_event_deserialization() {
    let json_data = aliases_event();

    let aliases = assert_matches!(
        from_json_value::<AnyTimelineEvent>(json_data),
        Ok(AnyTimelineEvent::State(
            AnyStateEvent::RoomAliases(StateEvent::Original(OriginalStateEvent {
                content: RoomAliasesEventContent {
                    aliases,
                    ..
                },
                ..
            }))
        )) => aliases
    );
    assert_eq!(aliases, vec![room_alias_id!("#somewhere:localhost")]);
}

#[test]
fn alias_event_field_access() {
    let json_data = aliases_event();

    let state_event = assert_matches!(
        from_json_value::<AnyTimelineEvent>(json_data.clone()),
        Ok(AnyTimelineEvent::State(state_event)) => state_event
    );
    assert_eq!(state_event.state_key(), "room.com");
    assert_eq!(state_event.room_id(), "!room:room.com");
    assert_eq!(state_event.event_id(), "$152037280074GZeOm:localhost");
    assert_eq!(state_event.sender(), "@example:localhost");

    let deser = from_json_value::<AnyStateEvent>(json_data).unwrap();
    let ev = assert_matches!(&deser, AnyStateEvent::RoomAliases(StateEvent::Original(ev)) => ev);
    assert_eq!(ev.content.aliases, vec![room_alias_id!("#somewhere:localhost")]);
    assert_eq!(deser.event_type().to_string(), "m.room.aliases");
}

#[test]
fn ephemeral_event_deserialization() {
    let json_data = json!({
        "content": {
            "user_ids": [
                "@alice:matrix.org",
                "@bob:example.com"
            ]
        },
        "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
        "type": "m.typing"
    });

    let ephem = assert_matches!(
        from_json_value::<AnyEphemeralRoomEvent>(json_data),
        Ok(ephem @ AnyEphemeralRoomEvent::Typing(_)) => ephem
    );
    assert_eq!(ephem.room_id(), "!jEsUZKDJdhlrceRyVU:example.org");
}

#[test]
fn serialize_and_deserialize_from_display_form() {
    serde_json_eq(MessageLikeEventType::CallAnswer, json!("m.call.answer"));
    serde_json_eq(GlobalAccountDataEventType::Direct, json!("m.direct"));
    serde_json_eq(RoomAccountDataEventType::FullyRead, json!("m.fully_read"));
    serde_json_eq(ToDeviceEventType::KeyVerificationKey, json!("m.key.verification.key"));
    serde_json_eq(StateEventType::RoomCreate, json!("m.room.create"));
    serde_json_eq(EphemeralRoomEventType::Typing, json!("m.typing"));
}
<|endoftext|>


<commit_before>//***************************************************************************
//
// In the end this file should be auto-generated with the varlink-generator
// from the corresponding varlink file.
//
//***************************************************************************

use std::result::Result;
use std::convert::From;

use varlink;

pub trait Interface: varlink::server::Interface {
    fn info(&self, i64) -> Result<InfoReply, Error>;
    fn list(&self) -> Result<ListReply, Error>;
}

#[macro_export]
macro_rules! IoSystemdNetwork {
	(
		()
		$(pub)* struct $name:ident $($_tail:tt)*
	) => {

impl varlink::server::Interface for $name {
    fn get_description(&self) -> &'static str {
        r#"
# Provides information about network state
interface io.systemd.network

type NetdevInfo (
  ifindex: int,
  ifname: string
)

type Netdev (
  ifindex: int,
  ifname: string
)

# Returns information about a network device
method Info(ifindex: int) -> (info: NetdevInfo)

# Lists all network devices
method List() -> (netdevs: Netdev[])

error UnknownNetworkDevice ()
error UnknownError (text: string)
	"#
    }

    fn get_name(&self) -> &'static str {
        "io.systemd.network"
    }

    fn call(&self, req: varlink::server::Request) -> Result<serde_json::Value, varlink::server::Error> {
        match req.method.as_ref() {
            "io.systemd.network.Info" => {
                if let Some(args) = req.parameters {
                    let infoargs: Result<InfoArgs, serde_json::Error> =
                        serde_json::from_value(args);
                    match infoargs {
                        Ok(args) => Ok(serde_json::to_value(self.info(args.ifindex)?)?),
                        Err(e) => Err(varlink::server::VarlinkError::InvalidParameter(Some(e.to_string().into())).into())
                    }
                } else {
                    Err(varlink::server::VarlinkError::InvalidParameter(None).into())
                }
            }
            "io.systemd.network.List" => Ok(serde_json::to_value(self.list()?)?),
            m => {
                let method: String = m.clone().into();
                Err(varlink::server::VarlinkError::MethodNotFound(Some(method.into())).into())
            }
        }
    }
}
};
}

#[derive(Debug)]
pub enum Error {
    UnknownNetworkDevice,
}

impl From<Error> for varlink::server::Error {
    fn from(e: Error) -> Self {
        varlink::server::Error {
            error: match e {
                Error::UnknownNetworkDevice => "io.systemd.network.UnknownNetworkDevice".into(),
            },
            parameters: match e {
                _ => None,
            },
        }
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct NetdevInfo {
    pub ifindex: i64,
    pub ifname: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Netdev {
    pub ifindex: i64,
    pub ifname: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct InfoArgs {
    pub ifindex: i64,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct InfoReply {
    pub info: NetdevInfo,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct ListReply {
    pub netdevs: Vec<Netdev>,
}
<commit_msg>rearrange<commit_after>use std::result::Result;
use std::convert::From;

use varlink;

#[derive(Serialize, Deserialize, Debug)]
pub struct Netdev {
    pub ifindex: i64,
    pub ifname: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct NetdevInfo {
    pub ifindex: i64,
    pub ifname: String,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct InfoReply {
    pub info: NetdevInfo,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct InfoArgs {
    pub ifindex: i64,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct ListReply {
    pub netdevs: Vec<Netdev>,
}

pub trait Interface: varlink::server::Interface {
    fn info(&self, i64) -> Result<InfoReply, Error>;
    fn list(&self) -> Result<ListReply, Error>;
}

#[macro_export]
macro_rules! IoSystemdNetwork {
	(
		()
		$(pub)* struct $name:ident $($_tail:tt)*
	) => {

impl varlink::server::Interface for $name {
    fn get_description(&self) -> &'static str {
        r#"
# Provides information about network state
interface io.systemd.network

type NetdevInfo (
  ifindex: int,
  ifname: string
)

type Netdev (
  ifindex: int,
  ifname: string
)

# Returns information about a network device
method Info(ifindex: int) -> (info: NetdevInfo)

# Lists all network devices
method List() -> (netdevs: Netdev[])

error UnknownNetworkDevice ()
error UnknownError (text: string)
	"#
    }

    fn get_name(&self) -> &'static str {
        "io.systemd.network"
    }

    fn call(&self, req: varlink::server::Request) -> Result<serde_json::Value, varlink::server::Error> {
        match req.method.as_ref() {
            "io.systemd.network.Info" => {
                if let Some(args) = req.parameters {
                    let args: InfoArgs = serde_json::from_value(args)?;
                    return Ok(serde_json::to_value(self.info(args.ifindex)?)?);
                } else {
                    return Err(varlink::server::VarlinkError::InvalidParameter(None).into());
                }
            }
            "io.systemd.network.List" => { return Ok(serde_json::to_value(self.list()?)?); }
            m => {
                let method: String = m.clone().into();
                return Err(varlink::server::VarlinkError::MethodNotFound(Some(method.into())).into());
            }
        }
    }
}
};
}

#[derive(Debug)]
pub enum Error {
    UnknownNetworkDevice,
}

impl From<Error> for varlink::server::Error {
    fn from(e: Error) -> Self {
        varlink::server::Error {
            error: match e {
                Error::UnknownNetworkDevice => "io.systemd.network.UnknownNetworkDevice".into(),
            },
            parameters: match e {
                _ => None,
            },
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::ffi::CString;
use std::iter::repeat;

use llvm_safe::id;
use llvm_safe::llvm;
use llvm_safe::llvm::{Constant, Type, Function, Value};
use llvm_safe::llvm::LLVMRealPredicate;

use kaleidoscope_lib::ast;

pub struct Context<'cid: 'context, 'context: 'module, 'module> {
    context: &'context llvm::Context<'cid>,
    module: llvm::ModuleBuilder<'cid, 'context, 'module>
}

impl<'cid, 'context, 'module> Context<'cid, 'context, 'module> {
    pub fn new(context: &'context llvm::Context<'cid>, module: llvm::ModuleBuilder<'cid, 'context, 'module>) -> Self {
        Context {
            context: context,
            module: module
        }
    }

    pub fn trans_expr<'fid, 'block>(&mut self, expr: &ast::Expr, fbuilder: &mut llvm::FunctionBuilder<'cid, 'fid, 'block>, builder: &mut llvm::PositionedBuilder<'cid, 'context, 'fid, 'block>, named_values: &HashMap<&str, &'block Value<'cid, 'fid>>) -> Result<&'block Value<'cid, 'fid>, &'static str> {
        match *expr {
            ast::Expr::Number(value) => Ok(Constant::f64(value, self.context).as_value()),
            ast::Expr::Variable(ref name) => named_values.get(&**name).cloned().ok_or("Unknown name in trans"),
            ast::Expr::BinaryOp(op, ref lhs, ref rhs) => {
                let lhs_val = try!(self.trans_expr(lhs, fbuilder, builder, named_values));
                let rhs_val = try!(self.trans_expr(rhs, fbuilder, builder, named_values));

                match op {
                    '+' => {
                        Ok(builder.fadd(lhs_val, rhs_val, const_cstr!("addtmp").as_cstr()))
                    },
                    '-' => {
                        Ok(builder.fsub(lhs_val, rhs_val, const_cstr!("subtmp").as_cstr()))
                    },
                    '*' => {
                        Ok(builder.fmul(lhs_val, rhs_val, const_cstr!("multmp").as_cstr()))
                    },
                    '/' => {
                        Ok(builder.fdiv(lhs_val, rhs_val, const_cstr!("divtmp").as_cstr()))
                    },
                    '<' => {
                        let cmp = builder.fcmp(LLVMRealPredicate::LLVMRealULT, lhs_val, rhs_val, const_cstr!("cmptmp").as_cstr());
                        Ok(builder.ui_to_fp(cmp, Type::f64(self.context), const_cstr!("convtmp").as_cstr()))
                    },
                    '>' => {
                        let cmp = builder.fcmp(LLVMRealPredicate::LLVMRealUGT, lhs_val, rhs_val, const_cstr!("cmptmp").as_cstr());
                        Ok(builder.ui_to_fp(cmp, Type::f64(self.context), const_cstr!("convtmp").as_cstr()))
                    },
                    _ => Err("Unknown operation in trans")
                }
            },
            ast::Expr::Call(ref name, ref args) => {
                let c_name = CString::new(&**name).unwrap();
                match self.module.get_named_function(&c_name) {
                    Some(func) => {
                        if func.num_args() != args.len() {
                            return Err("Calling function with incorrect arity");
                        }

                        let arg_vals = args.iter().map(|arg| self.trans_expr(arg, fbuilder, builder, named_values).unwrap()).collect::<Vec<_>>();

                        Ok(builder.call(func, &arg_vals, const_cstr!("calltmp").as_cstr()))
                    },
                    None => Err("Calling function that does not exist")
                }
            },
            ast::Expr::If(ref cond_expr, ref then_expr, ref else_expr) => {
                let (then_label, then_block) = fbuilder.append_basic_block(const_cstr!("then").as_cstr(), self.context);
                let (else_label, else_block) = fbuilder.append_basic_block(const_cstr!("else").as_cstr(), self.context);
                let (cont_label, cont_block) = fbuilder.append_basic_block(const_cstr!("ifcont").as_cstr(), self.context);

                let cond_val = try!(self.trans_expr(cond_expr, fbuilder, builder, named_values));
                let cond_val = builder.fcmp(LLVMRealPredicate::LLVMRealONE, cond_val, Constant::f64(0.0, self.context).as_value(), const_cstr!("ifcond").as_cstr());
                builder.cond_br(cond_val, then_label, else_label);

                builder.position_at_end(then_block);
                let then_val = try!(self.trans_expr(then_expr, fbuilder, builder, named_values));
                builder.br(cont_label);

                builder.position_at_end(else_block);
                let else_val = try!(self.trans_expr(else_expr, fbuilder, builder, named_values));
                builder.br(cont_label);

                builder.position_at_end(cont_block);
                let phi = builder.phi(Type::f64(self.context), const_cstr!("iftmp").as_cstr());
                phi.add_incoming_branch(then_val, then_label);
                phi.add_incoming_branch(else_val, else_label);
                Ok(phi.as_value())
            }
        }
    }

    pub fn trans_proto(&mut self, proto: &ast::Prototype) -> Result<&'module mut Function<'cid>, &'static str> {
        let c_name = &CString::new(&*proto.name).unwrap();
        if self.module.get_named_function(&c_name).is_some() {
            return Err("Redefinition of already defined function");
         }

        let f64_type = Type::f64(self.context);
        let arg_types = repeat(f64_type).take(proto.args.len()).collect::<Vec<_>>();
        let func_type = Type::function(&arg_types, f64_type);

        let mut function = self.module.add_function(&c_name, func_type);

        for (index, arg_name) in proto.args.iter().enumerate() {
            let c_arg_name = CString::new(&**arg_name).unwrap();
            id::with(|fid| {
                function.builder(fid).param(index as u32).set_name(&c_arg_name);
            });
        }

        Ok(function)
    }

    pub fn trans_func(&mut self, func: &ast::Function, builder: &mut llvm::Builder<'cid, 'context>) -> Result<&'module mut Function<'cid>, &'static str> {
        let mut function = try!(self.trans_proto(&func.proto));
        try!(id::with(|function_id| {
            let mut function_builder = function.builder(function_id);
            let named_values = func.proto.args.iter().enumerate().map(|(index, name)| (&**name, function_builder.param(index as u32))).collect();
            let (_, entry_bb) = function_builder.append_basic_block(const_cstr!("entry").as_cstr(), self.context);
            let builder = builder.position_at_end(entry_bb);

            let ret_val = try!(self.trans_expr(&func.body, &mut function_builder, builder, &named_values));
            builder.ret(ret_val);

            Ok(())
        }));

        function.verify();

        Ok(function)
    }
}
<commit_msg>Clean up Kaleidoscope trans nits<commit_after>use std::collections::HashMap;
use std::ffi::CString;
use std::iter::repeat;

use llvm_safe::id;
use llvm_safe::llvm;
use llvm_safe::llvm::{Constant, Type, Function, Value};
use llvm_safe::llvm::LLVMRealPredicate;

use kaleidoscope_lib::ast;

pub struct Context<'cid: 'context, 'context: 'module, 'module> {
    context: &'context llvm::Context<'cid>,
    module: llvm::ModuleBuilder<'cid, 'context, 'module>
}

impl<'cid, 'context, 'module> Context<'cid, 'context, 'module> {
    pub fn new(context: &'context llvm::Context<'cid>, module: llvm::ModuleBuilder<'cid, 'context, 'module>) -> Self {
        Context {
            context: context,
            module: module
        }
    }

    pub fn trans_expr<'fid, 'block>(&mut self, expr: &ast::Expr, fbuilder: &mut llvm::FunctionBuilder<'cid, 'fid, 'block>, builder: &mut llvm::PositionedBuilder<'cid, 'context, 'fid, 'block>, named_values: &HashMap<&str, &'block Value<'cid, 'fid>>) -> Result<&'block Value<'cid, 'fid>, &'static str> {
        match *expr {
            ast::Expr::Number(value) => Ok(Constant::f64(value, self.context).as_value()),
            ast::Expr::Variable(ref name) => named_values.get(&**name).cloned().ok_or("Unknown name in trans"),
            ast::Expr::BinaryOp(op, ref lhs, ref rhs) => {
                let lhs_val = try!(self.trans_expr(lhs, fbuilder, builder, named_values));
                let rhs_val = try!(self.trans_expr(rhs, fbuilder, builder, named_values));

                match op {
                    '+' => Ok(builder.fadd(lhs_val, rhs_val, const_cstr!("addtmp").as_cstr())),
                    '-' => Ok(builder.fsub(lhs_val, rhs_val, const_cstr!("subtmp").as_cstr())),
                    '*' => Ok(builder.fmul(lhs_val, rhs_val, const_cstr!("multmp").as_cstr())),
                    '/' => Ok(builder.fdiv(lhs_val, rhs_val, const_cstr!("divtmp").as_cstr())),
                    '<' => {
                        let cmp = builder.fcmp(LLVMRealPredicate::LLVMRealULT, lhs_val, rhs_val, const_cstr!("cmptmp").as_cstr());
                        Ok(builder.ui_to_fp(cmp, Type::f64(self.context), const_cstr!("convtmp").as_cstr()))
                    },
                    '>' => {
                        let cmp = builder.fcmp(LLVMRealPredicate::LLVMRealUGT, lhs_val, rhs_val, const_cstr!("cmptmp").as_cstr());
                        Ok(builder.ui_to_fp(cmp, Type::f64(self.context), const_cstr!("convtmp").as_cstr()))
                    },
                    _ => Err("Unknown operation in trans")
                }
            },
            ast::Expr::Call(ref name, ref args) => {
                let c_name = CString::new(&**name).unwrap();
                match self.module.get_named_function(&c_name) {
                    Some(func) => {
                        if func.num_args() != args.len() {
                            return Err("Calling function with incorrect arity");
                        }

                        let arg_vals = args.iter().map(|arg| self.trans_expr(arg, fbuilder, builder, named_values).unwrap()).collect::<Vec<_>>();

                        Ok(builder.call(func, &arg_vals, const_cstr!("calltmp").as_cstr()))
                    },
                    None => Err("Calling function that does not exist")
                }
            },
            ast::Expr::If(ref cond_expr, ref then_expr, ref else_expr) => {
                let (then_label, then_block) = fbuilder.append_basic_block(const_cstr!("then").as_cstr(), self.context);
                let (else_label, else_block) = fbuilder.append_basic_block(const_cstr!("else").as_cstr(), self.context);
                let (cont_label, cont_block) = fbuilder.append_basic_block(const_cstr!("ifcont").as_cstr(), self.context);

                let cond_val = try!(self.trans_expr(cond_expr, fbuilder, builder, named_values));
                let cond_val = builder.fcmp(LLVMRealPredicate::LLVMRealONE, cond_val, Constant::f64(0.0, self.context).as_value(), const_cstr!("ifcond").as_cstr());
                builder.cond_br(cond_val, then_label, else_label);

                builder.position_at_end(then_block);
                let then_val = try!(self.trans_expr(then_expr, fbuilder, builder, named_values));
                builder.br(cont_label);

                builder.position_at_end(else_block);
                let else_val = try!(self.trans_expr(else_expr, fbuilder, builder, named_values));
                builder.br(cont_label);

                builder.position_at_end(cont_block);
                let phi = builder.phi(Type::f64(self.context), const_cstr!("iftmp").as_cstr());
                phi.add_incoming_branch(then_val, then_label);
                phi.add_incoming_branch(else_val, else_label);
                Ok(phi.as_value())
            }
        }
    }

    pub fn trans_proto(&mut self, proto: &ast::Prototype) -> Result<&'module mut Function<'cid>, &'static str> {
        let c_name = &CString::new(&*proto.name).unwrap();
        if self.module.get_named_function(&c_name).is_some() {
            return Err("Redefinition of already defined function");
         }

        let f64_type = Type::f64(self.context);
        let arg_types = repeat(f64_type).take(proto.args.len()).collect::<Vec<_>>();
        let func_type = Type::function(&arg_types, f64_type);

        let mut function = self.module.add_function(&c_name, func_type);

        for (index, arg_name) in proto.args.iter().enumerate() {
            let c_arg_name = CString::new(&**arg_name).unwrap();
            id::with(|fid| {
                function.builder(fid).param(index as u32).set_name(&c_arg_name);
            });
        }

        Ok(function)
    }

    pub fn trans_func(&mut self, func: &ast::Function, builder: &mut llvm::Builder<'cid, 'context>) -> Result<&'module mut Function<'cid>, &'static str> {
        let mut function = try!(self.trans_proto(&func.proto));
        try!(id::with(|function_id| {
            let mut function_builder = function.builder(function_id);
            let named_values = func.proto.args.iter().enumerate().map(|(index, name)| (&**name, function_builder.param(index as u32))).collect();
            let (_, entry_bb) = function_builder.append_basic_block(const_cstr!("entry").as_cstr(), self.context);
            let builder = builder.position_at_end(entry_bb);

            let ret_val = try!(self.trans_expr(&func.body, &mut function_builder, builder, &named_values));
            builder.ret(ret_val);

            Ok(())
        }));

        function.verify();

        Ok(function)
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(dead_code)]

extern crate syntax;
extern crate walkdir;

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

use self::walkdir::DirEntry;

pub mod eq;
pub mod parse;

pub fn check_min_stack() {
    let min_stack_value = match env::var("RUST_MIN_STACK") {
        Ok(s) => s,
        Err(_) => {
            env::set_var("RUST_MIN_STACK", 16000000.to_string());
            return;
        }
    };
    let min_stack_value: usize = min_stack_value
        .parse()
        .expect("RUST_MIN_STACK env var should be set since some tests require it.");
    assert!(min_stack_value >= 16_000_000);
}

/// Read the `ABORT_AFTER_FAILURE` environment variable, and parse it.
pub fn abort_after() -> usize {
    match env::var("ABORT_AFTER_FAILURE") {
        Ok(s) => s.parse().expect("failed to parse ABORT_AFTER_FAILURE"),
        Err(_) => std::usize::MAX,
    }
}

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }
    let path_string = path.to_string_lossy();
    let path_string = if cfg!(windows) {
        path_string.replace('\\', "/").into()
    } else {
        path_string
    };
    // TODO assert that parsing fails on the parse-fail cases
    if path_string.starts_with("tests/rust/src/test/parse-fail")
        || path_string.starts_with("tests/rust/src/test/compile-fail")
    {
        return false;
    }

    if path_string.starts_with("tests/rust/src/test/ui") {
        let stderr_path = path.with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    match path_string.as_ref() {
        // TODO better support for attributes
        //
        //      { #![foo] }
        "tests/rust/src/test/pretty/stmt_expr_attributes.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/cfg_stmt_expr.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/item-attributes.rs" |
        // Deprecated placement syntax
        "tests/rust/src/test/run-pass/new-box-syntax.rs" |
        // Deprecated placement syntax
        "tests/rust/src/test/run-pass/placement-in-syntax.rs" |
        // TODO inclusive range syntax
        "tests/rust/src/test/run-pass/range-inclusive-pattern-precedence.rs" |
        // TODO feature(extern_in_paths)
        //
        //      use extern::xcrate;
        "tests/rust/src/test/run-pass/rfc-2126-extern-absolute-paths/extern.rs" |
        // TODO
        "tests/rust/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_in_paths.rs" |
        "tests/rust/src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs" |
        "tests/rust/src/test/run-pass-fulldeps/proc-macro/macros-in-extern.rs" |
        "tests/rust/src/test/run-pass/async-await.rs" |
        "tests/rust/src/test/run-pass/issue-49632.rs" |
        "tests/rust/src/test/run-pass/label_break_value.rs" |
        "tests/rust/src/test/run-pass/macros-in-extern.rs" |
        "tests/rust/src/test/run-pass/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs" |
        "tests/rust/src/test/rustfix/missing-comma-in-match.rs" |
        "tests/rust/src/test/rustfix/str-as-char.rs" |
        "tests/rust/src/test/rustfix/tuple-float-index.rs" |
        "tests/rust/src/test/ui/obsolete-in-place/bad.rs" |
        "tests/rust/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs" |
        // not actually test cases
        "tests/rust/src/test/run-pass/auxiliary/macro-comma-support.rs" |
        "tests/rust/src/test/run-pass/auxiliary/macro-include-items-expr.rs" => false,
        _ => true,
    }
}

pub fn clone_rust() {
    let result = Command::new("tests/clone.sh").status().unwrap();
    println!("result: {}", result);
    assert!(result.success());
}
<commit_msg>Triage test case that requires extern_in_paths<commit_after>// Copyright 2018 Syn Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(dead_code)]

extern crate syntax;
extern crate walkdir;

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

use self::walkdir::DirEntry;

pub mod eq;
pub mod parse;

pub fn check_min_stack() {
    let min_stack_value = match env::var("RUST_MIN_STACK") {
        Ok(s) => s,
        Err(_) => {
            env::set_var("RUST_MIN_STACK", 16000000.to_string());
            return;
        }
    };
    let min_stack_value: usize = min_stack_value
        .parse()
        .expect("RUST_MIN_STACK env var should be set since some tests require it.");
    assert!(min_stack_value >= 16_000_000);
}

/// Read the `ABORT_AFTER_FAILURE` environment variable, and parse it.
pub fn abort_after() -> usize {
    match env::var("ABORT_AFTER_FAILURE") {
        Ok(s) => s.parse().expect("failed to parse ABORT_AFTER_FAILURE"),
        Err(_) => std::usize::MAX,
    }
}

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }
    let path_string = path.to_string_lossy();
    let path_string = if cfg!(windows) {
        path_string.replace('\\', "/").into()
    } else {
        path_string
    };
    // TODO assert that parsing fails on the parse-fail cases
    if path_string.starts_with("tests/rust/src/test/parse-fail")
        || path_string.starts_with("tests/rust/src/test/compile-fail")
    {
        return false;
    }

    if path_string.starts_with("tests/rust/src/test/ui") {
        let stderr_path = path.with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    match path_string.as_ref() {
        // TODO better support for attributes
        //
        //      { #![foo] }
        "tests/rust/src/test/pretty/stmt_expr_attributes.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/cfg_stmt_expr.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/item-attributes.rs" |
        // Deprecated placement syntax
        "tests/rust/src/test/run-pass/new-box-syntax.rs" |
        // Deprecated placement syntax
        "tests/rust/src/test/run-pass/placement-in-syntax.rs" |
        // TODO inclusive range syntax
        "tests/rust/src/test/run-pass/range-inclusive-pattern-precedence.rs" |
        // TODO feature(extern_in_paths)
        //
        //      use extern::xcrate;
        "tests/rust/src/test/run-make-fulldeps/save-analysis-rfc2126/extern_in_paths.rs" |
        "tests/rust/src/test/run-pass/rfc-2126-extern-absolute-paths/extern.rs" |
        // TODO
        "tests/rust/src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs" |
        "tests/rust/src/test/run-pass-fulldeps/proc-macro/macros-in-extern.rs" |
        "tests/rust/src/test/run-pass/async-await.rs" |
        "tests/rust/src/test/run-pass/issue-49632.rs" |
        "tests/rust/src/test/run-pass/label_break_value.rs" |
        "tests/rust/src/test/run-pass/macros-in-extern.rs" |
        "tests/rust/src/test/run-pass/rfc-2421-unreserve-pure-offsetof-sizeof-alignof.rs" |
        "tests/rust/src/test/rustfix/missing-comma-in-match.rs" |
        "tests/rust/src/test/rustfix/str-as-char.rs" |
        "tests/rust/src/test/rustfix/tuple-float-index.rs" |
        "tests/rust/src/test/ui/obsolete-in-place/bad.rs" |
        "tests/rust/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.rs" |
        // not actually test cases
        "tests/rust/src/test/run-pass/auxiliary/macro-comma-support.rs" |
        "tests/rust/src/test/run-pass/auxiliary/macro-include-items-expr.rs" => false,
        _ => true,
    }
}

pub fn clone_rust() {
    let result = Command::new("tests/clone.sh").status().unwrap();
    println!("result: {}", result);
    assert!(result.success());
}
<|endoftext|>


<commit_before>extern crate tiny_http;

use tiny_http::{Server, Response};
use std::net::{TcpStream, Shutdown};
use std::io::{copy, Write, Read};
use std::thread::{spawn, sleep};
use std::time::Duration;
use std::sync::mpsc::channel;
use std::sync::Arc;
use std::ops::Deref;

/// Stream that produces bytes very slowly
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
struct SlowByteSrc { val: u8, len: usize }
impl<'b> Read for SlowByteSrc {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        sleep(Duration::from_millis(100));
        let l = self.len.min(buf.len()).min(1000);
        buf[..l].fill(self.val);
        self.len -= l;
        Ok(l)
    }
}

/// crude impl of http `Transfer-Encoding: chunked`
fn encode_chunked(data: &mut dyn Read, output: &mut dyn Write) {
    let mut buf = [0u8; 4096];
    loop {
        let l = data.read(&mut buf).unwrap();
        write!(output, "{:X}\r\n", l).unwrap();
        output.write_all(&buf[..l]).unwrap();
        write!(output, "\r\n").unwrap();
        if l == 0 { break; }
    }
}

mod prompt_pipelining {
    use super::*;

    /// Check that pipelined requests on the same connection are received promptly.
    fn assert_requests_parsed_promptly(
        req_cnt: usize,
        req_body: &'static [u8],
        timeout: Duration,
        req_writer: impl FnOnce(&mut dyn Write) + Send + 'static
    ) {
        let resp_body = SlowByteSrc { val: 42, len: 1000_000 }; // very slow response body

        let server = Server::http("0.0.0.0:0").unwrap();
        let mut client = TcpStream::connect(server.server_addr()).unwrap();
        let (svr_send, svr_rcv) = channel();

        spawn(move || {
            for _ in 0..req_cnt {
                let mut req = server.recv().unwrap();
                // read the whole body of the request
                let mut body = Vec::new();
                req.as_reader().read_to_end(&mut body).unwrap();
                assert_eq!(req_body, body.as_slice());
                // The next pipelined request should now be available for parsing,
                // while we send the (possibly slow) response in another thread
                spawn(move || req.respond(
                    Response::empty(200).with_data(resp_body, Some(resp_body.len))
                ));
            }
            svr_send.send(()).unwrap();
        });

        spawn(move || req_writer(&mut client));

        // requests must be sent and received quickly (before timeout expires)
        svr_rcv.recv_timeout(timeout)
            .expect("Server did not finish reading pipelined requests quickly enough");
    }

    // short (but not trivial) request body
    const REQ_BODY: &'static [u8] = &[65; 5000];

    #[test]
    fn content_length() {
        assert_requests_parsed_promptly(5, REQ_BODY, Duration::from_millis(200), move |wr| {
            for _ in 0..5 {
                write!(wr, "GET / HTTP/1.1\r\n").unwrap();
                write!(wr, "Connection: keep-alive\r\n").unwrap();
                write!(wr, "Content-Length: {}\r\n\r\n", REQ_BODY.len()).unwrap();
                wr.write_all(REQ_BODY).unwrap();
            }
        });
    }

    #[test]
    fn expect_continue() {
        assert_requests_parsed_promptly(5, REQ_BODY, Duration::from_millis(200), move |wr| {
            for _ in 0..5 {
                write!(wr, "GET / HTTP/1.1\r\n").unwrap();
                write!(wr, "Connection: keep-alive\r\n").unwrap();
                write!(wr, "Expect: 100 continue\r\n").unwrap();
                write!(wr, "Content-Length: {}\r\n\r\n", REQ_BODY.len()).unwrap();
                wr.write_all(REQ_BODY).unwrap();
            }
        });
    }

    #[test]
    fn chunked() {
        assert_requests_parsed_promptly(5, REQ_BODY, Duration::from_millis(200), move |wr| {
            for _ in 0..5 {
                write!(wr, "GET / HTTP/1.1\r\n").unwrap();
                write!(wr, "Connection: keep-alive\r\n").unwrap();
                write!(wr, "Transfer-Encoding: chunked\r\n\r\n").unwrap();
                let mut body = REQ_BODY;
                encode_chunked(&mut body, wr);
            }
        });
    }
}

mod prompt_responses {
    use super::*;

    /// Check that response is sent promptly without waiting for full request body.
    fn assert_responds_promptly(
        timeout: Duration,
        req_writer: impl FnOnce(&mut dyn Write) + Send + 'static
    ) {
        let server = Server::http("0.0.0.0:0").unwrap();
        let client = TcpStream::connect(server.server_addr()).unwrap();

        spawn(move || loop {
            // server attempts to respond immediately
            let req = server.recv().unwrap();
            req.respond(Response::empty(400)).unwrap();
        });

        let client = Arc::new(client);
        let client_write = Arc::clone(&client);
        // request written (possibly very slowly) in another thread
        spawn(move || req_writer(&mut client_write.deref()));

        // response should arrive quickly (before timeout expires)
        client.set_read_timeout(Some(timeout)).unwrap();
        let resp = client.deref().read(&mut [0u8; 4096]);
        client.shutdown(Shutdown::Both).unwrap();
        assert!(resp.is_ok(), "Server response was not sent promptly");
    }

    static SLOW_BODY: SlowByteSrc = SlowByteSrc { val: 65, len: 1000_000 };

    #[test]
    fn content_length_http11() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.1\r\n").unwrap();
            write!(wr, "Content-Length: {}\r\n\r\n", SLOW_BODY.len).unwrap();
            copy(&mut SLOW_BODY.clone(), wr).unwrap();
        });
    }

    #[test]
    fn content_length_http10() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.0\r\n").unwrap();
            write!(wr, "Content-Length: {}\r\n\r\n", SLOW_BODY.len).unwrap();
            copy(&mut SLOW_BODY.clone(), wr).unwrap();
        });
    }

    #[test]
    fn expect_continue() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.1\r\n").unwrap();
            write!(wr, "Expect: 100 continue\r\n").unwrap();
            write!(wr, "Content-Length: {}\r\n\r\n", SLOW_BODY.len).unwrap();
            copy(&mut SLOW_BODY.clone(), wr).unwrap();
        });
    }

    #[test]
    fn chunked() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.1\r\n").unwrap();
            write!(wr, "Transfer-Encoding: chunked\r\n\r\n").unwrap();
            encode_chunked(&mut SLOW_BODY.clone(), wr);
        });
    }
}<commit_msg>Remove test for prompt handling of requests with `Expect: 100-continue`<commit_after>extern crate tiny_http;

use tiny_http::{Server, Response};
use std::net::{TcpStream, Shutdown};
use std::io::{copy, Write, Read};
use std::thread::{spawn, sleep};
use std::time::Duration;
use std::sync::mpsc::channel;
use std::sync::Arc;
use std::ops::Deref;

/// Stream that produces bytes very slowly
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
struct SlowByteSrc { val: u8, len: usize }
impl<'b> Read for SlowByteSrc {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        sleep(Duration::from_millis(100));
        let l = self.len.min(buf.len()).min(1000);
        buf[..l].fill(self.val);
        self.len -= l;
        Ok(l)
    }
}

/// crude impl of http `Transfer-Encoding: chunked`
fn encode_chunked(data: &mut dyn Read, output: &mut dyn Write) {
    let mut buf = [0u8; 4096];
    loop {
        let l = data.read(&mut buf).unwrap();
        write!(output, "{:X}\r\n", l).unwrap();
        output.write_all(&buf[..l]).unwrap();
        write!(output, "\r\n").unwrap();
        if l == 0 { break; }
    }
}

mod prompt_pipelining {
    use super::*;

    /// Check that pipelined requests on the same connection are received promptly.
    fn assert_requests_parsed_promptly(
        req_cnt: usize,
        req_body: &'static [u8],
        timeout: Duration,
        req_writer: impl FnOnce(&mut dyn Write) + Send + 'static
    ) {
        let resp_body = SlowByteSrc { val: 42, len: 1000_000 }; // very slow response body

        let server = Server::http("0.0.0.0:0").unwrap();
        let mut client = TcpStream::connect(server.server_addr()).unwrap();
        let (svr_send, svr_rcv) = channel();

        spawn(move || {
            for _ in 0..req_cnt {
                let mut req = server.recv().unwrap();
                // read the whole body of the request
                let mut body = Vec::new();
                req.as_reader().read_to_end(&mut body).unwrap();
                assert_eq!(req_body, body.as_slice());
                // The next pipelined request should now be available for parsing,
                // while we send the (possibly slow) response in another thread
                spawn(move || req.respond(
                    Response::empty(200).with_data(resp_body, Some(resp_body.len))
                ));
            }
            svr_send.send(()).unwrap();
        });

        spawn(move || req_writer(&mut client));

        // requests must be sent and received quickly (before timeout expires)
        svr_rcv.recv_timeout(timeout)
            .expect("Server did not finish reading pipelined requests quickly enough");
    }

    // short (but not trivial) request body
    const REQ_BODY: &'static [u8] = &[65; 5000];

    #[test]
    fn content_length() {
        assert_requests_parsed_promptly(5, REQ_BODY, Duration::from_millis(200), move |wr| {
            for _ in 0..5 {
                write!(wr, "GET / HTTP/1.1\r\n").unwrap();
                write!(wr, "Connection: keep-alive\r\n").unwrap();
                write!(wr, "Content-Length: {}\r\n\r\n", REQ_BODY.len()).unwrap();
                wr.write_all(REQ_BODY).unwrap();
            }
        });
    }

    #[test]
    fn chunked() {
        assert_requests_parsed_promptly(5, REQ_BODY, Duration::from_millis(200), move |wr| {
            for _ in 0..5 {
                write!(wr, "GET / HTTP/1.1\r\n").unwrap();
                write!(wr, "Connection: keep-alive\r\n").unwrap();
                write!(wr, "Transfer-Encoding: chunked\r\n\r\n").unwrap();
                let mut body = REQ_BODY;
                encode_chunked(&mut body, wr);
            }
        });
    }
}

mod prompt_responses {
    use super::*;

    /// Check that response is sent promptly without waiting for full request body.
    fn assert_responds_promptly(
        timeout: Duration,
        req_writer: impl FnOnce(&mut dyn Write) + Send + 'static
    ) {
        let server = Server::http("0.0.0.0:0").unwrap();
        let client = TcpStream::connect(server.server_addr()).unwrap();

        spawn(move || loop {
            // server attempts to respond immediately
            let req = server.recv().unwrap();
            req.respond(Response::empty(400)).unwrap();
        });

        let client = Arc::new(client);
        let client_write = Arc::clone(&client);
        // request written (possibly very slowly) in another thread
        spawn(move || req_writer(&mut client_write.deref()));

        // response should arrive quickly (before timeout expires)
        client.set_read_timeout(Some(timeout)).unwrap();
        let resp = client.deref().read(&mut [0u8; 4096]);
        client.shutdown(Shutdown::Both).unwrap();
        assert!(resp.is_ok(), "Server response was not sent promptly");
    }

    static SLOW_BODY: SlowByteSrc = SlowByteSrc { val: 65, len: 1000_000 };

    #[test]
    fn content_length_http11() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.1\r\n").unwrap();
            write!(wr, "Content-Length: {}\r\n\r\n", SLOW_BODY.len).unwrap();
            copy(&mut SLOW_BODY.clone(), wr).unwrap();
        });
    }

    #[test]
    fn content_length_http10() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.0\r\n").unwrap();
            write!(wr, "Content-Length: {}\r\n\r\n", SLOW_BODY.len).unwrap();
            copy(&mut SLOW_BODY.clone(), wr).unwrap();
        });
    }

    #[test]
    fn expect_continue() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.1\r\n").unwrap();
            write!(wr, "Expect: 100 continue\r\n").unwrap();
            write!(wr, "Content-Length: {}\r\n\r\n", SLOW_BODY.len).unwrap();
            copy(&mut SLOW_BODY.clone(), wr).unwrap();
        });
    }

    #[test]
    fn chunked() {
        assert_responds_promptly(Duration::from_millis(200), move |wr| {
            write!(wr, "GET / HTTP/1.1\r\n").unwrap();
            write!(wr, "Transfer-Encoding: chunked\r\n\r\n").unwrap();
            encode_chunked(&mut SLOW_BODY.clone(), wr);
        });
    }
}<|endoftext|>


<commit_before>use std::collections::BTreeMap;

use crate::{DeviceIdBox, KeyNameBox, ServerNameBox, SigningKeyId, UserId};

/// Map of key identifier to signature values.
pub type EntitySignatures<K> = BTreeMap<SigningKeyId<K>, String>;

/// Map of all signatures, grouped by entity
///
/// ```
/// # use ruma_identifiers::{server_name, KeyId, Signatures, SigningKeyAlgorithm};
/// let key_identifier = KeyId::from_parts(SigningKeyAlgorithm::Ed25519, "1");
/// let mut signatures = Signatures::new();
/// let server_name = server_name!("example.org");
/// let signature = "YbJva03ihSj5mPk+CHMJKUKlCXCPFXjXOK6VqBnN9nA2evksQcTGn6hwQfrgRHIDDXO2le49x7jnWJHMJrJoBQ";
/// signatures.insert(server_name, key_identifier, signature.into());
/// ```
#[derive(Clone, Debug, Default)]
pub struct Signatures<E: Ord, K: ?Sized>(BTreeMap<E, EntitySignatures<K>>);

impl<E: Ord, K: ?Sized> Signatures<E, K> {
    /// Creates an empty signature map.
    pub fn new() -> Self {
        Self(BTreeMap::new())
    }

    /// Add a signature for the given server name and key identifier.
    ///
    /// If there was already one, it is returned.
    pub fn insert(
        &mut self,
        entity: E,
        key_identifier: SigningKeyId<K>,
        value: String,
    ) -> Option<String> {
        self.0.entry(entity).or_insert_with(Default::default).insert(key_identifier, value)
    }
}

/// Map of server signatures for an event, grouped by server.
pub type ServerSignatures = Signatures<ServerNameBox, KeyNameBox>;

/// Map of device signatures for an event, grouped by user.
pub type DeviceSignatures = Signatures<UserId, DeviceIdBox>;
<commit_msg>identifiers: Add get method to Signatures<commit_after>use std::{borrow::Borrow, collections::BTreeMap};

use crate::{DeviceIdBox, KeyNameBox, ServerNameBox, SigningKeyId, UserId};

/// Map of key identifier to signature values.
pub type EntitySignatures<K> = BTreeMap<SigningKeyId<K>, String>;

/// Map of all signatures, grouped by entity
///
/// ```
/// # use ruma_identifiers::{server_name, KeyId, Signatures, SigningKeyAlgorithm};
/// let key_identifier = KeyId::from_parts(SigningKeyAlgorithm::Ed25519, "1");
/// let mut signatures = Signatures::new();
/// let server_name = server_name!("example.org");
/// let signature = "YbJva03ihSj5mPk+CHMJKUKlCXCPFXjXOK6VqBnN9nA2evksQcTGn6hwQfrgRHIDDXO2le49x7jnWJHMJrJoBQ";
/// signatures.insert(server_name, key_identifier, signature.into());
/// ```
#[derive(Clone, Debug, Default)]
pub struct Signatures<E: Ord, K: ?Sized>(BTreeMap<E, EntitySignatures<K>>);

impl<E: Ord, K: ?Sized> Signatures<E, K> {
    /// Creates an empty signature map.
    pub fn new() -> Self {
        Self(BTreeMap::new())
    }

    /// Add a signature for the given server name and key identifier.
    ///
    /// If there was already one, it is returned.
    pub fn insert(
        &mut self,
        entity: E,
        key_identifier: SigningKeyId<K>,
        value: String,
    ) -> Option<String> {
        self.0.entry(entity).or_insert_with(Default::default).insert(key_identifier, value)
    }

    /// Returns a reference to the signatures corresponding to the entities.
    pub fn get<Q>(&self, entity: &Q) -> Option<&EntitySignatures<K>>
    where
        E: Borrow<Q>,
        Q: Ord + ?Sized,
    {
        self.0.get(entity)
    }
}

/// Map of server signatures for an event, grouped by server.
pub type ServerSignatures = Signatures<ServerNameBox, KeyNameBox>;

/// Map of device signatures for an event, grouped by user.
pub type DeviceSignatures = Signatures<UserId, DeviceIdBox>;
<|endoftext|>


<commit_before>use std::{
    convert::TryInto,
    iter::FromIterator,
    num::TryFromIntError,
};

use serde::{
    Deserialize,
    Serialize,
};

use thiserror::Error;

use rnc_core::{
    urs,
    urs_taxid,
};

use crate::sequences::{
    accession::{
        AccessionVec,
        CrossReference,
        RawAccession,
        ReferenceVec,
    },
    basic::Basic,
    crs::{
        Crs,
        CrsVec,
    },
    feedback::{
        Feedback,
        FeedbackVec,
    },
    go_annotation::GoAnnotation,
    interacting_protein::InteractingProtein,
    interacting_rna::InteractingRna,
    locus::LocusInfo,
    orf::{
        Orf,
        OrfVec,
    },
    precompute::{
        Precompute,
        PrecomputeSummary,
    },
    qa_status::QaStatus,
    r2dt::R2dt,
    rfam_hit::{
        RfamHit,
        RfamHitVec,
    },
    so_tree,
};

#[derive(Error, Debug)]
pub enum NormalizationError {
    #[error("Could not parse {0}")]
    UrsParsingError(#[from] urs::Error),

    #[error("Could not parse {0}")]
    UrsTaxidParsingError(#[from] urs_taxid::Error),

    #[error("Could not convert {0} to urs number")]
    UrsNumberError(#[from] TryFromIntError),
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Raw {
    pub id: usize,
    pub base: Basic,
    pub crs: Vec<Crs>,
    pub feedback: Vec<Feedback>,
    pub go_annotations: Vec<GoAnnotation>,
    pub interacting_proteins: Vec<InteractingProtein>,
    pub interacting_rnas: Vec<InteractingRna>,
    pub locus_info: Option<LocusInfo>,
    pub precompute: Precompute,
    pub qa_status: QaStatus,
    pub r2dt: Option<R2dt>,
    pub rfam_hits: Vec<RfamHit>,
    pub orfs: Vec<Orf>,
    pub so_tree: so_tree::SoTree,
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Normalized {
    urs: String,
    taxid: usize,
    urs_taxid: String,
    short_urs: String,
    deleted: String,
    qa_status: QaStatus,
    secondary: Option<R2dt>,
    cross_references: Vec<CrossReference>,
    crs: CrsVec,
    overlaps: FeedbackVec,
    go_annotations: Vec<GoAnnotation>,
    interacting_proteins: Vec<InteractingProtein>,
    interacting_rnas: Vec<InteractingRna>,
    so_rna_type_tree: so_tree::SoTree,
    locus_info: Option<LocusInfo>,

    #[serde(flatten)]
    orfs: OrfVec,

    #[serde(flatten)]
    pre_summary: PrecomputeSummary,

    #[serde(flatten)]
    basic: Basic,

    #[serde(flatten)]
    accessions: AccessionVec,

    #[serde(flatten)]
    references: ReferenceVec,

    #[serde(flatten)]
    rfam_hits: RfamHitVec,
    /* #[serde(flatten)]
     * dates: Dates, */
}

impl Raw {
    pub fn id(&self) -> usize {
        return self.id
    }

    pub fn urs_taxid(&self) -> String {
        return self.base.urs_taxid.to_owned();
    }

    pub fn urs(&self) -> Result<String, urs_taxid::Error> {
        let ut: urs_taxid::UrsTaxid = self.urs_taxid().parse()?;
        let urs: urs::Urs = ut.into();
        Ok(urs.to_string())
    }

    pub fn taxid(&self) -> Result<u64, urs_taxid::Error> {
        let ut: urs_taxid::UrsTaxid = self.urs_taxid().parse()?;
        Ok(ut.taxid())
    }

    pub fn short_urs(&self) -> Result<String, urs_taxid::Error> {
        let ut: urs_taxid::UrsTaxid = self.urs_taxid().parse()?;
        let urs: urs::Urs = ut.into();
        Ok(urs.short_urs())
    }

    pub fn short_urs_taxid(&self) -> Result<String, urs_taxid::Error> {
        let ut: urs_taxid::UrsTaxid = self.urs_taxid().parse()?;
        Ok(ut.short())
    }
}

impl Normalized {
    pub fn new(raw: Raw, accessions: Vec<RawAccession>) -> Result<Self, NormalizationError> {
        let pre_summary = PrecomputeSummary::from(raw.precompute);
        let base = raw.base.clone();

        let urs_taxid = base.urs_taxid.to_owned();
        assert!(
            urs_taxid == accessions[0].urs_taxid,
            "Accession urs {} and base urs {} disagree for id {}",
            accessions[0].urs_taxid,
            urs_taxid,
            base.id
        );
        let parsed: urs_taxid::UrsTaxid = urs_taxid.parse()?;
        let references = ReferenceVec::from_iter(accessions.clone());

        Ok(Self {
            urs_taxid,
            urs: parsed.urs().to_string(),
            taxid: parsed.taxid().try_into()?,
            short_urs: parsed.short(),
            deleted: String::from("N"),
            so_rna_type_tree: raw.so_tree,
            pre_summary,
            basic: base,
            qa_status: raw.qa_status,
            secondary: raw.r2dt,
            accessions: AccessionVec::from_iter(accessions.clone()),
            cross_references: accessions.into_iter().map(CrossReference::from).collect(),
            crs: raw.crs.into_iter().collect(),
            overlaps: raw.feedback.into_iter().collect(),
            go_annotations: raw.go_annotations,
            interacting_proteins: raw.interacting_proteins,
            interacting_rnas: raw.interacting_rnas,
            references,
            rfam_hits: raw.rfam_hits.into_iter().collect(),
            orfs: raw.orfs.into_iter().collect(),
            locus_info: raw.locus_info,
        })
    }

    pub fn urs_taxid(&self) -> &str {
        &self.urs_taxid
    }

    pub fn is_locus_member(&self) -> bool {
        self.locus_info.is_some()
    }

    pub fn locus_id(&self) -> Option<usize> {
        self.locus_info.as_ref().map(|l| l.locus_id())
    }

    pub fn cross_references(&self) -> &Vec<CrossReference> {
        &self.cross_references
    }
}
<commit_msg>Do not duplicate urs_taxid field<commit_after>use std::{
    convert::TryInto,
    iter::FromIterator,
    num::TryFromIntError,
};

use serde::{
    Deserialize,
    Serialize,
};

use thiserror::Error;

use rnc_core::{
    urs,
    urs_taxid,
};

use crate::sequences::{
    accession::{
        AccessionVec,
        CrossReference,
        RawAccession,
        ReferenceVec,
    },
    basic::Basic,
    crs::{
        Crs,
        CrsVec,
    },
    feedback::{
        Feedback,
        FeedbackVec,
    },
    go_annotation::GoAnnotation,
    interacting_protein::InteractingProtein,
    interacting_rna::InteractingRna,
    locus::LocusInfo,
    orf::{
        Orf,
        OrfVec,
    },
    precompute::{
        Precompute,
        PrecomputeSummary,
    },
    qa_status::QaStatus,
    r2dt::R2dt,
    rfam_hit::{
        RfamHit,
        RfamHitVec,
    },
    so_tree,
};

#[derive(Error, Debug)]
pub enum NormalizationError {
    #[error("Could not parse {0}")]
    UrsParsingError(#[from] urs::Error),

    #[error("Could not parse {0}")]
    UrsTaxidParsingError(#[from] urs_taxid::Error),

    #[error("Could not convert {0} to urs number")]
    UrsNumberError(#[from] TryFromIntError),
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Raw {
    pub id: usize,
    pub base: Basic,
    pub crs: Vec<Crs>,
    pub feedback: Vec<Feedback>,
    pub go_annotations: Vec<GoAnnotation>,
    pub interacting_proteins: Vec<InteractingProtein>,
    pub interacting_rnas: Vec<InteractingRna>,
    pub locus_info: Option<LocusInfo>,
    pub precompute: Precompute,
    pub qa_status: QaStatus,
    pub r2dt: Option<R2dt>,
    pub rfam_hits: Vec<RfamHit>,
    pub orfs: Vec<Orf>,
    pub so_tree: so_tree::SoTree,
}

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Normalized {
    urs: String,
    taxid: usize,
    short_urs: String,
    deleted: String,
    qa_status: QaStatus,
    secondary: Option<R2dt>,
    cross_references: Vec<CrossReference>,
    crs: CrsVec,
    overlaps: FeedbackVec,
    go_annotations: Vec<GoAnnotation>,
    interacting_proteins: Vec<InteractingProtein>,
    interacting_rnas: Vec<InteractingRna>,
    so_rna_type_tree: so_tree::SoTree,
    locus_info: Option<LocusInfo>,

    #[serde(flatten)]
    orfs: OrfVec,

    #[serde(flatten)]
    pre_summary: PrecomputeSummary,

    #[serde(flatten)]
    basic: Basic,

    #[serde(flatten)]
    accessions: AccessionVec,

    #[serde(flatten)]
    references: ReferenceVec,

    #[serde(flatten)]
    rfam_hits: RfamHitVec,
    /* #[serde(flatten)]
     * dates: Dates, */
}

impl Raw {
    pub fn id(&self) -> usize {
        return self.id
    }

    pub fn urs_taxid(&self) -> String {
        return self.base.urs_taxid.to_owned();
    }

    pub fn urs(&self) -> Result<String, urs_taxid::Error> {
        let ut: urs_taxid::UrsTaxid = self.urs_taxid().parse()?;
        let urs: urs::Urs = ut.into();
        Ok(urs.to_string())
    }

    pub fn taxid(&self) -> Result<u64, urs_taxid::Error> {
        let ut: urs_taxid::UrsTaxid = self.urs_taxid().parse()?;
        Ok(ut.taxid())
    }

    pub fn short_urs(&self) -> Result<String, urs_taxid::Error> {
        let ut: urs_taxid::UrsTaxid = self.urs_taxid().parse()?;
        let urs: urs::Urs = ut.into();
        Ok(urs.short_urs())
    }

    pub fn short_urs_taxid(&self) -> Result<String, urs_taxid::Error> {
        let ut: urs_taxid::UrsTaxid = self.urs_taxid().parse()?;
        Ok(ut.short())
    }
}

impl Normalized {
    pub fn new(raw: Raw, accessions: Vec<RawAccession>) -> Result<Self, NormalizationError> {
        let pre_summary = PrecomputeSummary::from(raw.precompute);
        let base = raw.base.clone();

        let urs_taxid = base.urs_taxid.to_owned();
        assert!(
            urs_taxid == accessions[0].urs_taxid,
            "Accession urs {} and base urs {} disagree for id {}",
            accessions[0].urs_taxid,
            urs_taxid,
            base.id
        );
        let parsed: urs_taxid::UrsTaxid = urs_taxid.parse()?;
        let references = ReferenceVec::from_iter(accessions.clone());

        Ok(Self {
            urs: parsed.urs().to_string(),
            taxid: parsed.taxid().try_into()?,
            short_urs: parsed.short(),
            deleted: String::from("N"),
            so_rna_type_tree: raw.so_tree,
            pre_summary,
            basic: base,
            qa_status: raw.qa_status,
            secondary: raw.r2dt,
            accessions: AccessionVec::from_iter(accessions.clone()),
            cross_references: accessions.into_iter().map(CrossReference::from).collect(),
            crs: raw.crs.into_iter().collect(),
            overlaps: raw.feedback.into_iter().collect(),
            go_annotations: raw.go_annotations,
            interacting_proteins: raw.interacting_proteins,
            interacting_rnas: raw.interacting_rnas,
            references,
            rfam_hits: raw.rfam_hits.into_iter().collect(),
            orfs: raw.orfs.into_iter().collect(),
            locus_info: raw.locus_info,
        })
    }

    pub fn urs_taxid(&self) -> &str {
        &self.basic.urs_taxid
    }

    pub fn is_locus_member(&self) -> bool {
        self.locus_info.is_some()
    }

    pub fn locus_id(&self) -> Option<usize> {
        self.locus_info.as_ref().map(|l| l.locus_id())
    }

    pub fn cross_references(&self) -> &Vec<CrossReference> {
        &self.cross_references
    }
}
<|endoftext|>


<commit_before><commit_msg>togglerecord: Notify main_stream_cond on release_pad<commit_after><|endoftext|>