client-api: Make more types in search_events non-exhaustive

This commit is contained in:
Jonas Platte 2020-08-18 04:14:40 +02:00
parent d7c977e593
commit 6df02fc7e2
No known key found for this signature in database
GPG Key ID: 7D261D771D915378

View File

@ -74,6 +74,7 @@ impl<'a> Categories<'a> {
/// Criteria for searching a category of events. /// Criteria for searching a category of events.
#[derive(Clone, Copy, Debug, Outgoing, Serialize)] #[derive(Clone, Copy, Debug, Outgoing, Serialize)]
#[non_exhaustive]
pub struct Criteria<'a> { pub struct Criteria<'a> {
/// The string to search events for. /// The string to search events for.
pub search_term: &'a str, pub search_term: &'a str,
@ -91,20 +92,36 @@ pub struct Criteria<'a> {
pub order_by: Option<OrderBy>, pub order_by: Option<OrderBy>,
/// Configures whether any context for the events returned are included in the response. /// Configures whether any context for the events returned are included in the response.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "EventContext::is_default")]
pub event_context: Option<EventContext>, pub event_context: EventContext,
/// Requests the server return the current state for each room returned. /// Requests the server return the current state for each room returned.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub include_state: Option<bool>, pub include_state: Option<bool>,
/// Requests that the server partitions the result set based on the provided list of keys. /// Requests that the server partitions the result set based on the provided list of keys.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Groupings::is_empty")]
pub groupings: Option<Groupings<'a>>, pub groupings: Groupings<'a>,
}
impl<'a> Criteria<'a> {
/// Creates a new `Criteria` with the given search term.
pub fn new(search_term: &'a str) -> Self {
Self {
search_term,
keys: None,
filter: None,
order_by: None,
event_context: Default::default(),
include_state: None,
groupings: Default::default(),
}
}
} }
/// Configures whether any context for the events returned are included in the response. /// Configures whether any context for the events returned are included in the response.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct EventContext { pub struct EventContext {
/// How many events before the result are returned. /// How many events before the result are returned.
#[serde( #[serde(
@ -135,8 +152,33 @@ fn is_default_event_context_limit(val: &UInt) -> bool {
*val == default_event_context_limit() *val == default_event_context_limit()
} }
impl EventContext {
/// Creates an `EventContext` with all-default values.
pub fn new() -> Self {
Self {
before_limit: default_event_context_limit(),
after_limit: default_event_context_limit(),
include_profile: false,
}
}
/// Returns whether all fields have their default value.
pub fn is_default(&self) -> bool {
self.before_limit == default_event_context_limit()
&& self.after_limit == default_event_context_limit()
&& !self.include_profile
}
}
impl Default for EventContext {
fn default() -> Self {
Self::new()
}
}
/// Context for search results, if requested. /// Context for search results, if requested.
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[non_exhaustive]
pub struct EventContextResult { pub struct EventContextResult {
/// Pagination token for the end of the chunk. /// Pagination token for the end of the chunk.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
@ -151,23 +193,53 @@ pub struct EventContextResult {
pub events_before: Vec<Raw<AnyEvent>>, pub events_before: Vec<Raw<AnyEvent>>,
/// The historic profile information of the users that sent the events returned. /// The historic profile information of the users that sent the events returned.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub profile_info: Option<BTreeMap<UserId, UserProfile>>, pub profile_info: BTreeMap<UserId, UserProfile>,
/// Pagination token for the start of the chunk. /// Pagination token for the start of the chunk.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub start: Option<String>, pub start: Option<String>,
} }
impl EventContextResult {
/// Creates an empty `EventContextResult`.
pub fn new() -> Self {
Default::default()
}
/// Returns whether all fields are `None` or an empty list.
pub fn is_empty(&self) -> bool {
self.end.is_none()
&& self.events_after.is_empty()
&& self.events_before.is_empty()
&& self.profile_info.is_empty()
&& self.start.is_none()
}
}
/// A grouping for partioning the result set. /// A grouping for partioning the result set.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)] #[derive(Clone, Copy, Default, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct Grouping { pub struct Grouping {
/// The key within events to use for this grouping. /// The key within events to use for this grouping.
pub key: Option<GroupingKey>, pub key: Option<GroupingKey>,
} }
impl Grouping {
/// Creates an empty `Grouping`.
pub fn new() -> Self {
Default::default()
}
/// Returns whether `key` is `None`.
pub fn is_empty(&self) -> bool {
self.key.is_none()
}
}
/// The key within events to use for this grouping. /// The key within events to use for this grouping.
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, PartialOrd, Ord, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, PartialOrd, Ord, Serialize)]
#[non_exhaustive]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum GroupingKey { pub enum GroupingKey {
/// `room_id` /// `room_id`
@ -178,15 +250,30 @@ pub enum GroupingKey {
} }
/// Requests that the server partitions the result set based on the provided list of keys. /// Requests that the server partitions the result set based on the provided list of keys.
#[derive(Clone, Copy, Debug, Outgoing, Serialize)] #[derive(Clone, Copy, Default, Debug, Outgoing, Serialize)]
#[incoming_derive(Default)]
#[non_exhaustive]
pub struct Groupings<'a> { pub struct Groupings<'a> {
/// List of groups to request. /// List of groups to request.
#[serde(default, skip_serializing_if = "<[_]>::is_empty")] #[serde(default, skip_serializing_if = "<[_]>::is_empty")]
pub group_by: &'a [Grouping], pub group_by: &'a [Grouping],
} }
impl<'a> Groupings<'a> {
/// Creates an empty `Groupings`.
pub fn new() -> Self {
Default::default()
}
/// Returns `true` if all fields are empty.
pub fn is_empty(&self) -> bool {
self.group_by.is_empty()
}
}
/// The keys to search for. /// The keys to search for.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub enum SearchKeys { pub enum SearchKeys {
/// content.body /// content.body
#[serde(rename = "content.body")] #[serde(rename = "content.body")]
@ -203,6 +290,7 @@ pub enum SearchKeys {
/// The order in which to search for results. /// The order in which to search for results.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)] #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[non_exhaustive]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum OrderBy { pub enum OrderBy {
/// Prioritize recent events. /// Prioritize recent events.
@ -214,20 +302,31 @@ pub enum OrderBy {
} }
/// Categories of events that can be searched for. /// Categories of events that can be searched for.
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Default, Debug, Deserialize, Serialize)]
#[non_exhaustive]
pub struct ResultCategories { pub struct ResultCategories {
/// Room event results. /// Room event results.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "ResultRoomEvents::is_empty")]
pub room_events: Option<ResultRoomEvents>, pub room_events: ResultRoomEvents,
}
impl ResultCategories {
/// Creates an empty `ResultCategories`.
pub fn new() -> Self {
Default::default()
}
} }
/// Categories of events that can be searched for. /// Categories of events that can be searched for.
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[non_exhaustive]
pub struct ResultRoomEvents { pub struct ResultRoomEvents {
/// An approximate count of the total number of results found. /// An approximate count of the total number of results found.
pub count: UInt, #[serde(skip_serializing_if = "Option::is_none")]
pub count: Option<UInt>,
/// Any groups that were requested. /// Any groups that were requested.
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub groups: BTreeMap<GroupingKey, BTreeMap<RoomIdOrUserId, ResultGroup>>, pub groups: BTreeMap<GroupingKey, BTreeMap<RoomIdOrUserId, ResultGroup>>,
/// Token that can be used to get the next batch of results, by passing as the `next_batch` /// Token that can be used to get the next batch of results, by passing as the `next_batch`
@ -236,6 +335,7 @@ pub struct ResultRoomEvents {
pub next_batch: Option<String>, pub next_batch: Option<String>,
/// List of results in the requested order. /// List of results in the requested order.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub results: Vec<SearchResult>, pub results: Vec<SearchResult>,
/// The current state for every room in the results. This is included if the request had the /// The current state for every room in the results. This is included if the request had the
@ -249,8 +349,26 @@ pub struct ResultRoomEvents {
pub highlights: Vec<String>, pub highlights: Vec<String>,
} }
impl ResultRoomEvents {
/// Creates an empty `ResultRoomEvents`.
pub fn new() -> Self {
Default::default()
}
/// Returns `true` if all fields are empty / `None`.
pub fn is_empty(&self) -> bool {
self.count.is_none()
&& self.groups.is_empty()
&& self.next_batch.is_none()
&& self.results.is_empty()
&& self.state.is_empty()
&& self.highlights.is_empty()
}
}
/// A grouping of results, if requested. /// A grouping of results, if requested.
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[non_exhaustive]
pub struct ResultGroup { pub struct ResultGroup {
/// Token that can be used to get the next batch of results in the group, by passing as the /// Token that can be used to get the next batch of results in the group, by passing as the
/// `next_batch` parameter to the next call. If this field is absent, there are no more /// `next_batch` parameter to the next call. If this field is absent, there are no more
@ -259,18 +377,33 @@ pub struct ResultGroup {
pub next_batch: Option<String>, pub next_batch: Option<String>,
/// Key that can be used to order different groups. /// Key that can be used to order different groups.
pub order: UInt, #[serde(skip_serializing_if = "Option::is_none")]
pub order: Option<UInt>,
/// Which results are in this group. /// Which results are in this group.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub results: Vec<EventId>, pub results: Vec<EventId>,
} }
impl ResultGroup {
/// Creates an empty `ResultGroup`.
pub fn new() -> Self {
Default::default()
}
/// Returns `true` if all fields are empty / `None`.
pub fn is_empty(&self) -> bool {
self.next_batch.is_none() && self.order.is_none() && self.results.is_empty()
}
}
/// A search result. /// A search result.
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[non_exhaustive]
pub struct SearchResult { pub struct SearchResult {
/// Context for result, if requested. /// Context for result, if requested.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "EventContextResult::is_empty")]
pub context: Option<EventContextResult>, pub context: EventContextResult,
/// A number that describes how closely this result matches the search. Higher is closer. /// A number that describes how closely this result matches the search. Higher is closer.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
@ -281,8 +414,21 @@ pub struct SearchResult {
pub result: Option<Raw<AnyEvent>>, pub result: Option<Raw<AnyEvent>>,
} }
impl SearchResult {
/// Creates an empty `SearchResult`.
pub fn new() -> Self {
Default::default()
}
/// Returns `true` if all fields are empty / `None`.
pub fn is_empty(&self) -> bool {
self.context.is_empty() && self.rank.is_none() && self.result.is_none()
}
}
/// A user profile. /// A user profile.
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[non_exhaustive]
pub struct UserProfile { pub struct UserProfile {
/// The user's avatar URL, if set. /// The user's avatar URL, if set.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
@ -293,6 +439,18 @@ pub struct UserProfile {
pub displayname: Option<String>, pub displayname: Option<String>,
} }
impl UserProfile {
/// Creates an empty `UserProfile`.
pub fn new() -> Self {
Default::default()
}
/// Returns `true` if all fields are `None`.
pub fn is_empty(&self) -> bool {
self.avatar_url.is_none() && self.displayname.is_none()
}
}
/// Represents either a room or user ID for returning grouped search results. /// Represents either a room or user ID for returning grouped search results.
#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)] #[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
pub enum RoomIdOrUserId { pub enum RoomIdOrUserId {