Skip to main content

revolt_database/
lib.rs

1#[macro_use]
2extern crate serde;
3
4#[macro_use]
5extern crate async_recursion;
6
7#[macro_use]
8extern crate async_trait;
9
10#[macro_use]
11extern crate log;
12
13#[macro_use]
14extern crate revolt_optional_struct;
15
16#[macro_use]
17extern crate revolt_result;
18
19pub use iso8601_timestamp;
20
21#[cfg(feature = "mongodb")]
22pub use mongodb;
23
24#[cfg(feature = "mongodb")]
25#[macro_use]
26extern crate bson;
27
28#[cfg(not(feature = "tokio-runtime"))]
29compile_error!("tokio-runtime feature must be enabled.");
30
31#[macro_export]
32#[cfg(debug_assertions)]
33macro_rules! query {
34    ( $self: ident, $type: ident, $collection: expr, $($rest:expr),+ ) => {
35        Ok($self.$type($collection, $($rest),+).await.unwrap())
36    };
37}
38
39#[macro_export]
40#[cfg(not(debug_assertions))]
41macro_rules! query {
42    ( $self: ident, $type: ident, $collection: expr, $($rest:expr),+ ) => {
43        $self.$type($collection, $($rest),+).await
44            .map_err(|err| {
45                revolt_config::capture_internal_error!(err);
46                create_database_error!(stringify!($type), $collection)
47            })
48    };
49}
50
51macro_rules! database_derived {
52    ( $( $item:item )+ ) => {
53        $(
54            #[derive(Clone)]
55            $item
56        )+
57    };
58}
59
60macro_rules! auto_derived {
61    ( $( $item:item )+ ) => {
62        $(
63            #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
64            $item
65        )+
66    };
67}
68
69macro_rules! auto_derived_partial {
70    ( $item:item, $name:expr ) => {
71        #[derive(OptionalStruct, Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
72        #[optional_derive(Serialize, Deserialize, Debug, Clone, Default, Eq, PartialEq)]
73        #[optional_name = $name]
74        #[opt_skip_serializing_none]
75        #[opt_some_priority]
76        $item
77    };
78}
79
80/// Internal macro for `generate_diff!`, you should not need to use this yourself.
81macro_rules! generate_field_diff {
82    (optional, $remove:ident, $fieldsmember:path, $self:ident, $before:ident, $partial:ident, $field:ident) => {
83        if $partial.$field.is_some() || $remove.contains(&$fieldsmember) {
84            $before.$field = $self.$field.clone();
85        };
86    };
87
88    (optional, default, $remove:ident, $fieldsmember:path, $self:ident, $before:ident, $partial:ident, $field:ident) => {
89        if $partial.$field.is_some() || $remove.contains(&$fieldsmember) {
90            $before.$field = Some($self.$field.clone());
91        };
92    };
93
94    ($self:ident, $before:ident, $partial:ident, $field:ident) => {
95        if $partial.$field.is_some() {
96            $before.$field = Some($self.$field.clone());
97        };
98    };
99}
100
101/// Generates a partial model containing the data which has changed in an update
102///
103/// ## Usage:
104/// `before` is the "output" containing what the model had before being updated,
105/// this will corraspond to `partial` which is what the data is being changed too.
106///
107/// ```rs
108/// let mut before = PartialModel::default();
109///
110/// generate_diff!(
111///     self,  // database model
112///     before,  // mutable empty partial corrasponding to the current model
113///     partial,  // partial containing what is being updated
114///     remove,  // slice of fields being removed
115///     (
116///         name,  // regular non-nullable non-removable field
117///         (FieldsEnum::Nickname) nickname,  // optional removable field
118///         ((default) FieldsEnum::Roles) roles,  // optional removable field with custom default
119///     )
120/// );
121/// ```
122///
123/// See `Member::generate_diff` `Server::generate_diff` `Role::generate_diff` for full examples
124macro_rules! generate_diff {
125    (
126        $self:ident,
127        $before:ident,
128        $partial:ident,
129        $remove:ident,
130        (
131            $(
132                $(
133                    $(@$optional:tt)? (
134                        $($(@$default:tt)? (default))?
135                        $fieldsmember:path
136                    )
137                )?
138                $field: ident
139            ),*
140            $(,)?
141        )
142    ) => {
143        $(
144            generate_field_diff!(
145                $( $($optional)? optional, $($($default)? default,)? $remove, $fieldsmember,)?
146                $self, $before, $partial, $field
147            );
148        )*
149    }
150}
151
152mod drivers;
153pub use drivers::*;
154
155#[cfg(test)]
156macro_rules! database_test {
157    ( | $db: ident | $test:expr ) => {
158        let db = $crate::DatabaseInfo::Test(format!(
159            "{}:{}",
160            file!().replace('/', "_").replace(".rs", ""),
161            line!()
162        ))
163        .connect()
164        .await
165        .expect("Database connection failed.");
166
167        db.drop_database().await;
168
169        #[allow(clippy::redundant_closure_call)]
170        (|$db: $crate::Database| $test)(db.clone()).await;
171
172        db.drop_database().await
173    };
174}
175
176mod models;
177pub mod util;
178pub use models::*;
179
180pub mod events;
181#[cfg(feature = "tasks")]
182pub mod tasks;
183
184mod amqp;
185pub use amqp::amqp::AMQP;
186
187#[cfg(feature = "voice")]
188pub mod voice;
189
190/// Utility function to check if a boolean value is false
191pub fn if_false(t: &bool) -> bool {
192    !t
193}
194
195/// Utility function to check if an option doesnt contain true
196pub fn if_option_false(t: &Option<bool>) -> bool {
197    t != &Some(true)
198}