diff --git a/Cargo.lock b/Cargo.lock index 45fe73443..2427cbf24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -636,6 +636,25 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "cbindgen" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "485ede05a56152367a6ec586a7425b475d6c3d3838581ff651d2a6e3730a62ef" +dependencies = [ + "clap 3.1.8", + "heck", + "indexmap", + "log", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn", + "tempfile", + "toml", +] + [[package]] name = "cc" version = "1.0.73" @@ -712,6 +731,21 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "clap" +version = "3.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c" +dependencies = [ + "atty", + "bitflags", + "indexmap", + "os_str_bytes", + "strsim 0.10.0", + "termcolor", + "textwrap 0.15.0", +] + [[package]] name = "clear_on_drop" version = "0.2.4" @@ -836,7 +870,7 @@ dependencies = [ "async-std", "atty", "cast", - "clap", + "clap 2.34.0", "criterion-plot", "csv", "futures", @@ -1014,7 +1048,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.9.3", "syn", ] @@ -1154,6 +1188,7 @@ version = "1.76.0" dependencies = [ "anyhow", "async-std", + "cbindgen", "deltachat", "human-panic", "libc", @@ -1973,6 +2008,16 @@ dependencies = [ "nom 6.1.2", ] +[[package]] +name = "indexmap" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +dependencies = [ + "autocfg 1.1.0", + "hashbrown", +] + [[package]] name = "infer" version = "0.2.3" @@ -2509,6 +2554,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + [[package]] name = "os_type" version = "2.4.0" @@ -3636,6 +3690,12 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" version = "0.24.0" diff --git a/deltachat-ffi/Cargo.toml b/deltachat-ffi/Cargo.toml index 595b481ff..4c77f5c54 100644 --- a/deltachat-ffi/Cargo.toml +++ b/deltachat-ffi/Cargo.toml @@ -25,6 +25,9 @@ anyhow = "1" thiserror = "1" rand = "0.7" +[build-dependencies] +cbindgen = "0.21.0" + [features] default = ["vendored"] vendored = ["deltachat/vendored"] diff --git a/deltachat-ffi/bindings.h b/deltachat-ffi/bindings.h new file mode 100644 index 000000000..af486dc29 --- /dev/null +++ b/deltachat-ffi/bindings.h @@ -0,0 +1,600 @@ +#ifndef __DELTACHAT_H__ +#define __DELTACHAT_H__ + +/* Generated with cbindgen:0.21.0 */ + +/* WARNING: this file is autogenerated by cbindgen. Do not modify manually. */ + +#ifndef PY_CFFI +#include +#include +#endif + + +#define DC_CONNECTIVITY_CONNECTING 2000 + +#define DC_CONNECTIVITY_WORKING 3000 + +#define DC_CONNECTIVITY_CONNECTED 4000 + +typedef struct dc_provider_t dc_provider_t; + +typedef struct dc_accounts_event_emitter_t dc_accounts_event_emitter_t; + +/** + * Struct representing a list of deltachat accounts. + */ +typedef struct dc_accounts_t dc_accounts_t; + +typedef struct dc_array_t dc_array_t; + +typedef struct dc_chat_t dc_chat_t; + +typedef struct dc_chatlist_t dc_chatlist_t; + +typedef struct dc_contact_t dc_contact_t; + +/** + * Struct representing the deltachat context. + */ +typedef struct dc_context_t dc_context_t; + +typedef struct dc_event_emitter_t dc_event_emitter_t; + +typedef struct dc_event_t dc_event_t; + +/** + * An object containing a set of values. + * The meaning of the values is defined by the function returning the object. + * Lot objects are created + * eg. by chatlist.get_summary() or dc_msg_get_summary(). + * + * *Lot* is used in the meaning *heap* here. + */ +typedef struct dc_lot_t dc_lot_t; + +typedef struct dc_msg_t dc_msg_t; + +typedef struct dc_provider_t dc_provider_t; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +struct dc_context_t *dc_context_new(const char *_os_name, const char *dbfile, const char *blobdir); + +struct dc_context_t *dc_context_new_closed(const char *dbfile); + +int dc_context_open(struct dc_context_t *context, const char *passphrase); + +int dc_context_is_open(struct dc_context_t *context); + +/** + * Release the context structure. + * + * This function releases the memory of the `dc_context_t` structure. + */ +void dc_context_unref(struct dc_context_t *context); + +char *dc_get_blobdir(struct dc_context_t *context); + +int dc_set_config(struct dc_context_t *context, const char *key, const char *value); + +char *dc_get_config(struct dc_context_t *context, const char *key); + +int dc_set_stock_translation(struct dc_context_t *context, uint32_t stock_id, char *stock_msg); + +int dc_set_config_from_qr(struct dc_context_t *context, char *qr); + +char *dc_get_info(const struct dc_context_t *context); + +int dc_get_connectivity(const struct dc_context_t *context); + +char *dc_get_connectivity_html(const struct dc_context_t *context); + +int dc_all_work_done(struct dc_context_t *context); + +char *dc_get_oauth2_url(struct dc_context_t *context, const char *addr, const char *redirect); + +void dc_configure(struct dc_context_t *context); + +int dc_is_configured(struct dc_context_t *context); + +void dc_start_io(struct dc_context_t *context); + +int dc_get_id(struct dc_context_t *context); + +void dc_event_unref(struct dc_event_t *a); + +int dc_event_get_id(struct dc_event_t *event); + +int dc_event_get_data1_int(struct dc_event_t *event); + +int dc_event_get_data2_int(struct dc_event_t *event); + +char *dc_event_get_data2_str(struct dc_event_t *event); + +uint32_t dc_event_get_account_id(struct dc_event_t *event); + +struct dc_event_emitter_t *dc_get_event_emitter(struct dc_context_t *context); + +void dc_event_emitter_unref(struct dc_event_emitter_t *emitter); + +struct dc_event_t *dc_get_next_event(struct dc_event_emitter_t *events); + +void dc_stop_io(struct dc_context_t *context); + +void dc_maybe_network(struct dc_context_t *context); + +int32_t dc_preconfigure_keypair(struct dc_context_t *context, + const char *addr, + const char *public_data, + const char *secret_data); + +struct dc_chatlist_t *dc_get_chatlist(struct dc_context_t *context, + int flags, + const char *query_str, + uint32_t query_id); + +uint32_t dc_create_chat_by_contact_id(struct dc_context_t *context, uint32_t contact_id); + +uint32_t dc_get_chat_id_by_contact_id(struct dc_context_t *context, uint32_t contact_id); + +uint32_t dc_prepare_msg(struct dc_context_t *context, uint32_t chat_id, struct dc_msg_t *msg); + +uint32_t dc_send_msg(struct dc_context_t *context, uint32_t chat_id, struct dc_msg_t *msg); + +uint32_t dc_send_msg_sync(struct dc_context_t *context, uint32_t chat_id, struct dc_msg_t *msg); + +uint32_t dc_send_text_msg(struct dc_context_t *context, uint32_t chat_id, const char *text_to_send); + +uint32_t dc_send_videochat_invitation(struct dc_context_t *context, uint32_t chat_id); + +int dc_send_webxdc_status_update(struct dc_context_t *context, + uint32_t msg_id, + const char *json, + const char *descr); + +char *dc_get_webxdc_status_updates(struct dc_context_t *context, + uint32_t msg_id, + uint32_t last_known_serial); + +void dc_set_draft(struct dc_context_t *context, uint32_t chat_id, struct dc_msg_t *msg); + +uint32_t dc_add_device_msg(struct dc_context_t *context, const char *label, struct dc_msg_t *msg); + +int dc_was_device_msg_ever_added(struct dc_context_t *context, const char *label); + +struct dc_msg_t *dc_get_draft(struct dc_context_t *context, uint32_t chat_id); + +dc_array_t *dc_get_chat_msgs(struct dc_context_t *context, + uint32_t chat_id, + uint32_t flags, + uint32_t marker1before); + +int dc_get_msg_cnt(struct dc_context_t *context, uint32_t chat_id); + +int dc_get_fresh_msg_cnt(struct dc_context_t *context, uint32_t chat_id); + +int dc_estimate_deletion_cnt(struct dc_context_t *context, int from_server, int64_t seconds); + +dc_array_t *dc_get_fresh_msgs(struct dc_context_t *context); + +void dc_marknoticed_chat(struct dc_context_t *context, uint32_t chat_id); + +dc_array_t *dc_get_chat_media(struct dc_context_t *context, + uint32_t chat_id, + int msg_type, + int or_msg_type2, + int or_msg_type3); + +uint32_t dc_get_next_media(struct dc_context_t *context, + uint32_t msg_id, + int dir, + int msg_type, + int or_msg_type2, + int or_msg_type3); + +int dc_set_chat_protection(struct dc_context_t *context, uint32_t chat_id, int protect); + +void dc_set_chat_visibility(struct dc_context_t *context, uint32_t chat_id, int archive); + +void dc_delete_chat(struct dc_context_t *context, uint32_t chat_id); + +void dc_block_chat(struct dc_context_t *context, uint32_t chat_id); + +void dc_accept_chat(struct dc_context_t *context, uint32_t chat_id); + +dc_array_t *dc_get_chat_contacts(struct dc_context_t *context, uint32_t chat_id); + +dc_array_t *dc_search_msgs(struct dc_context_t *context, uint32_t chat_id, const char *query); + +struct dc_chat_t *dc_get_chat(struct dc_context_t *context, uint32_t chat_id); + +uint32_t dc_create_group_chat(struct dc_context_t *context, int protect, const char *name); + +uint32_t dc_create_broadcast_list(struct dc_context_t *context); + +int dc_is_contact_in_chat(struct dc_context_t *context, uint32_t chat_id, uint32_t contact_id); + +int dc_add_contact_to_chat(struct dc_context_t *context, uint32_t chat_id, uint32_t contact_id); + +int dc_remove_contact_from_chat(struct dc_context_t *context, + uint32_t chat_id, + uint32_t contact_id); + +int dc_set_chat_name(struct dc_context_t *context, uint32_t chat_id, const char *name); + +int dc_set_chat_profile_image(struct dc_context_t *context, uint32_t chat_id, const char *image); + +int dc_set_chat_mute_duration(struct dc_context_t *context, uint32_t chat_id, int64_t duration); + +char *dc_get_chat_encrinfo(struct dc_context_t *context, uint32_t chat_id); + +uint32_t dc_get_chat_ephemeral_timer(struct dc_context_t *context, uint32_t chat_id); + +int dc_set_chat_ephemeral_timer(struct dc_context_t *context, uint32_t chat_id, uint32_t timer); + +char *dc_get_msg_info(struct dc_context_t *context, uint32_t msg_id); + +char *dc_get_msg_html(struct dc_context_t *context, uint32_t msg_id); + +char *dc_get_mime_headers(struct dc_context_t *context, uint32_t msg_id); + +void dc_delete_msgs(struct dc_context_t *context, const uint32_t *msg_ids, int msg_cnt); + +void dc_forward_msgs(struct dc_context_t *context, + const uint32_t *msg_ids, + int msg_cnt, + uint32_t chat_id); + +void dc_markseen_msgs(struct dc_context_t *context, const uint32_t *msg_ids, int msg_cnt); + +struct dc_msg_t *dc_get_msg(struct dc_context_t *context, uint32_t msg_id); + +void dc_download_full_msg(struct dc_context_t *context, uint32_t msg_id); + +int dc_may_be_valid_addr(const char *addr); + +uint32_t dc_lookup_contact_id_by_addr(struct dc_context_t *context, const char *addr); + +uint32_t dc_create_contact(struct dc_context_t *context, const char *name, const char *addr); + +int dc_add_address_book(struct dc_context_t *context, const char *addr_book); + +dc_array_t *dc_get_contacts(struct dc_context_t *context, uint32_t flags, const char *query); + +int dc_get_blocked_cnt(struct dc_context_t *context); + +dc_array_t *dc_get_blocked_contacts(struct dc_context_t *context); + +void dc_block_contact(struct dc_context_t *context, uint32_t contact_id, int block); + +char *dc_get_contact_encrinfo(struct dc_context_t *context, uint32_t contact_id); + +int dc_delete_contact(struct dc_context_t *context, uint32_t contact_id); + +struct dc_contact_t *dc_get_contact(struct dc_context_t *context, uint32_t contact_id); + +void dc_imex(struct dc_context_t *context, int what_raw, const char *param1, const char *param2); + +char *dc_imex_has_backup(struct dc_context_t *context, const char *dir); + +char *dc_initiate_key_transfer(struct dc_context_t *context); + +int dc_continue_key_transfer(struct dc_context_t *context, uint32_t msg_id, const char *setup_code); + +void dc_stop_ongoing_process(struct dc_context_t *context); + +struct dc_lot_t *dc_check_qr(struct dc_context_t *context, const char *qr); + +char *dc_get_securejoin_qr(struct dc_context_t *context, uint32_t chat_id); + +char *dc_get_securejoin_qr_svg(struct dc_context_t *context, uint32_t chat_id); + +uint32_t dc_join_securejoin(struct dc_context_t *context, const char *qr); + +void dc_send_locations_to_chat(struct dc_context_t *context, uint32_t chat_id, int seconds); + +int dc_is_sending_locations_to_chat(struct dc_context_t *context, uint32_t chat_id); + +int dc_set_location(struct dc_context_t *context, + double latitude, + double longitude, + double accuracy); + +dc_array_t *dc_get_locations(struct dc_context_t *context, + uint32_t chat_id, + uint32_t contact_id, + int64_t timestamp_begin, + int64_t timestamp_end); + +void dc_delete_all_locations(struct dc_context_t *context); + +char *dc_get_last_error(struct dc_context_t *context); + +void dc_array_unref(dc_array_t *a); + +size_t dc_array_get_cnt(const dc_array_t *array); + +uint32_t dc_array_get_id(const dc_array_t *array, size_t index); + +double dc_array_get_latitude(const dc_array_t *array, size_t index); + +double dc_array_get_longitude(const dc_array_t *array, size_t index); + +double dc_array_get_accuracy(const dc_array_t *array, size_t index); + +int64_t dc_array_get_timestamp(const dc_array_t *array, size_t index); + +unsigned int dc_array_get_chat_id(const dc_array_t *array, size_t index); + +unsigned int dc_array_get_contact_id(const dc_array_t *array, size_t index); + +unsigned int dc_array_get_msg_id(const dc_array_t *array, size_t index); + +char *dc_array_get_marker(const dc_array_t *array, size_t index); + +int dc_array_search_id(const dc_array_t *array, unsigned int needle, size_t *ret_index); + +void dc_chatlist_unref(struct dc_chatlist_t *chatlist); + +size_t dc_chatlist_get_cnt(struct dc_chatlist_t *chatlist); + +uint32_t dc_chatlist_get_chat_id(struct dc_chatlist_t *chatlist, size_t index); + +uint32_t dc_chatlist_get_msg_id(struct dc_chatlist_t *chatlist, size_t index); + +struct dc_lot_t *dc_chatlist_get_summary(struct dc_chatlist_t *chatlist, + size_t index, + struct dc_chat_t *chat); + +struct dc_lot_t *dc_chatlist_get_summary2(struct dc_context_t *context, + uint32_t chat_id, + uint32_t msg_id); + +const struct dc_context_t *dc_chatlist_get_context(struct dc_chatlist_t *chatlist); + +void dc_chat_unref(struct dc_chat_t *chat); + +uint32_t dc_chat_get_id(struct dc_chat_t *chat); + +int dc_chat_get_type(struct dc_chat_t *chat); + +char *dc_chat_get_name(struct dc_chat_t *chat); + +char *dc_chat_get_profile_image(struct dc_chat_t *chat); + +uint32_t dc_chat_get_color(struct dc_chat_t *chat); + +int dc_chat_get_visibility(struct dc_chat_t *chat); + +int dc_chat_is_contact_request(struct dc_chat_t *chat); + +int dc_chat_is_unpromoted(struct dc_chat_t *chat); + +int dc_chat_is_self_talk(struct dc_chat_t *chat); + +int dc_chat_is_device_talk(struct dc_chat_t *chat); + +int dc_chat_can_send(struct dc_chat_t *chat); + +int dc_chat_is_protected(struct dc_chat_t *chat); + +int dc_chat_is_sending_locations(struct dc_chat_t *chat); + +int dc_chat_is_muted(struct dc_chat_t *chat); + +int64_t dc_chat_get_remaining_mute_duration(struct dc_chat_t *chat); + +char *dc_chat_get_info_json(struct dc_context_t *context, uint32_t chat_id); + +struct dc_msg_t *dc_msg_new(struct dc_context_t *context, int viewtype); + +void dc_msg_unref(struct dc_msg_t *msg); + +uint32_t dc_msg_get_id(struct dc_msg_t *msg); + +uint32_t dc_msg_get_from_id(struct dc_msg_t *msg); + +uint32_t dc_msg_get_chat_id(struct dc_msg_t *msg); + +int dc_msg_get_viewtype(struct dc_msg_t *msg); + +int dc_msg_get_state(struct dc_msg_t *msg); + +int dc_msg_get_download_state(struct dc_msg_t *msg); + +int64_t dc_msg_get_timestamp(struct dc_msg_t *msg); + +int64_t dc_msg_get_received_timestamp(struct dc_msg_t *msg); + +int64_t dc_msg_get_sort_timestamp(struct dc_msg_t *msg); + +char *dc_msg_get_text(struct dc_msg_t *msg); + +char *dc_msg_get_subject(struct dc_msg_t *msg); + +char *dc_msg_get_file(struct dc_msg_t *msg); + +char *dc_msg_get_filename(struct dc_msg_t *msg); + +char *dc_msg_get_webxdc_blob(struct dc_msg_t *msg, const char *filename, size_t *ret_bytes); + +char *dc_msg_get_webxdc_info(struct dc_msg_t *msg); + +char *dc_msg_get_filemime(struct dc_msg_t *msg); + +uint64_t dc_msg_get_filebytes(struct dc_msg_t *msg); + +int dc_msg_get_width(struct dc_msg_t *msg); + +int dc_msg_get_height(struct dc_msg_t *msg); + +int dc_msg_get_duration(struct dc_msg_t *msg); + +int dc_msg_get_showpadlock(struct dc_msg_t *msg); + +int dc_msg_is_bot(struct dc_msg_t *msg); + +uint32_t dc_msg_get_ephemeral_timer(struct dc_msg_t *msg); + +int64_t dc_msg_get_ephemeral_timestamp(struct dc_msg_t *msg); + +struct dc_lot_t *dc_msg_get_summary(struct dc_msg_t *msg, struct dc_chat_t *chat); + +char *dc_msg_get_summarytext(struct dc_msg_t *msg, int approx_characters); + +char *dc_msg_get_override_sender_name(struct dc_msg_t *msg); + +int dc_msg_has_deviating_timestamp(struct dc_msg_t *msg); + +int dc_msg_has_location(struct dc_msg_t *msg); + +int dc_msg_is_sent(struct dc_msg_t *msg); + +int dc_msg_is_forwarded(struct dc_msg_t *msg); + +int dc_msg_is_info(struct dc_msg_t *msg); + +int dc_msg_get_info_type(struct dc_msg_t *msg); + +int dc_msg_is_increation(struct dc_msg_t *msg); + +int dc_msg_is_setupmessage(struct dc_msg_t *msg); + +int dc_msg_has_html(struct dc_msg_t *msg); + +char *dc_msg_get_videochat_url(struct dc_msg_t *msg); + +int dc_msg_get_videochat_type(struct dc_msg_t *msg); + +char *dc_msg_get_setupcodebegin(struct dc_msg_t *msg); + +void dc_msg_set_text(struct dc_msg_t *msg, const char *text); + +void dc_msg_set_html(struct dc_msg_t *msg, const char *html); + +void dc_msg_set_override_sender_name(struct dc_msg_t *msg, const char *name); + +void dc_msg_set_file(struct dc_msg_t *msg, const char *file, const char *filemime); + +void dc_msg_set_dimension(struct dc_msg_t *msg, int width, int height); + +void dc_msg_set_duration(struct dc_msg_t *msg, int duration); + +void dc_msg_set_location(struct dc_msg_t *msg, double latitude, double longitude); + +void dc_msg_latefiling_mediasize(struct dc_msg_t *msg, int width, int height, int duration); + +char *dc_msg_get_error(struct dc_msg_t *msg); + +void dc_msg_set_quote(struct dc_msg_t *msg, const struct dc_msg_t *quote); + +char *dc_msg_get_quoted_text(const struct dc_msg_t *msg); + +struct dc_msg_t *dc_msg_get_quoted_msg(const struct dc_msg_t *msg); + +struct dc_msg_t *dc_msg_get_parent(const struct dc_msg_t *msg); + +void dc_msg_force_plaintext(struct dc_msg_t *msg); + +void dc_contact_unref(struct dc_contact_t *contact); + +uint32_t dc_contact_get_id(struct dc_contact_t *contact); + +char *dc_contact_get_addr(struct dc_contact_t *contact); + +char *dc_contact_get_name(struct dc_contact_t *contact); + +char *dc_contact_get_auth_name(struct dc_contact_t *contact); + +char *dc_contact_get_display_name(struct dc_contact_t *contact); + +char *dc_contact_get_name_n_addr(struct dc_contact_t *contact); + +char *dc_contact_get_profile_image(struct dc_contact_t *contact); + +uint32_t dc_contact_get_color(struct dc_contact_t *contact); + +char *dc_contact_get_status(struct dc_contact_t *contact); + +int64_t dc_contact_get_last_seen(struct dc_contact_t *contact); + +int dc_contact_is_blocked(struct dc_contact_t *contact); + +int dc_contact_is_verified(struct dc_contact_t *contact); + +void dc_lot_unref(struct dc_lot_t *lot); + +char *dc_lot_get_text1(struct dc_lot_t *lot); + +char *dc_lot_get_text2(struct dc_lot_t *lot); + +int dc_lot_get_text1_meaning(struct dc_lot_t *lot); + +int dc_lot_get_state(struct dc_lot_t *lot); + +uint32_t dc_lot_get_id(struct dc_lot_t *lot); + +int64_t dc_lot_get_timestamp(struct dc_lot_t *lot); + +void dc_str_unref(char *s); + +const dc_provider_t *dc_provider_new_from_email(const struct dc_context_t *context, + const char *addr); + +char *dc_provider_get_overview_page(const dc_provider_t *provider); + +char *dc_provider_get_before_login_hint(const dc_provider_t *provider); + +int dc_provider_get_status(const dc_provider_t *provider); + +void dc_provider_unref(dc_provider_t *provider); + +struct dc_accounts_t *dc_accounts_new(const char *_os_name, const char *dbfile); + +/** + * Release the accounts structure. + * + * This function releases the memory of the `dc_accounts_t` structure. + */ +void dc_accounts_unref(struct dc_accounts_t *accounts); + +struct dc_context_t *dc_accounts_get_account(struct dc_accounts_t *accounts, uint32_t id); + +struct dc_context_t *dc_accounts_get_selected_account(struct dc_accounts_t *accounts); + +int dc_accounts_select_account(struct dc_accounts_t *accounts, uint32_t id); + +uint32_t dc_accounts_add_account(struct dc_accounts_t *accounts); + +uint32_t dc_accounts_add_closed_account(struct dc_accounts_t *accounts); + +int dc_accounts_remove_account(struct dc_accounts_t *accounts, uint32_t id); + +uint32_t dc_accounts_migrate_account(struct dc_accounts_t *accounts, const char *dbfile); + +dc_array_t *dc_accounts_get_all(struct dc_accounts_t *accounts); + +int dc_accounts_all_work_done(struct dc_accounts_t *accounts); + +void dc_accounts_start_io(struct dc_accounts_t *accounts); + +void dc_accounts_stop_io(struct dc_accounts_t *accounts); + +void dc_accounts_maybe_network(struct dc_accounts_t *accounts); + +void dc_accounts_maybe_network_lost(struct dc_accounts_t *accounts); + +struct dc_accounts_event_emitter_t *dc_accounts_get_event_emitter(struct dc_accounts_t *accounts); + +void dc_accounts_event_emitter_unref(struct dc_accounts_event_emitter_t *emitter); + +struct dc_event_t *dc_accounts_get_next_event(struct dc_accounts_event_emitter_t *emitter); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif /* __DELTACHAT_H__ */ diff --git a/deltachat-ffi/build.rs b/deltachat-ffi/build.rs index 701ed7d74..de25e67aa 100644 --- a/deltachat-ffi/build.rs +++ b/deltachat-ffi/build.rs @@ -32,4 +32,9 @@ fn main() { .unwrap() .write_all(pkg_config.as_bytes()) .unwrap(); + + let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + cbindgen::generate(crate_dir) + .expect("Unable to generate header file") + .write_to_file("bindings.h"); } diff --git a/deltachat-ffi/cbindgen.toml b/deltachat-ffi/cbindgen.toml new file mode 100644 index 000000000..373530bf3 --- /dev/null +++ b/deltachat-ffi/cbindgen.toml @@ -0,0 +1,43 @@ +language = "C" +include_guard = "__DELTACHAT_H__" +include_version = true +autogen_warning = "/* WARNING: this file is autogenerated by cbindgen. Do not modify manually. */" +# header = """ +# /* We start with a bunch of opaque `_dc_something_t` structs. */ +# """ +no_includes = true +after_includes = """ +#ifndef PY_CFFI +#include +#include +#endif +""" +cpp_compat = true +# style = "tag" +style = "both" +documentation = true +documentation_style = "doxy" +documentation_length = "full" + +[export] +# exclude = ["AccountsWrapper"] + +[export.rename] +# The opaque wrapper structs are usually prefixed with an underscore +# in C headers. To keep the Rust source clean we rename them here, +# though at the end of the day this doesn't really matter. +# "AccountsWrapper" = "_dc_accounts_t" +# "ChatWrapper" = "_dc_chat_t" +# "ChatlistWrapper" = "_dc_chatlist_t" +# "ContactWrapper" = "_dc_contact_t" +# "MessageWrapper" = "_dc_message_t" +# "Context" = "_dc_context_t" +# "Event" = "_dc_event_t" +# "EventEmitter" = "_dc_event_emitter_t" +# "AccountsEventEmitter" = "_dc_accounts_event_emitter_t" +# "Lot" = "_dc_lot_t" +"Provider" = "dc_provider_t" + +[parse] +parse_deps = true +include = ["deltachat"] \ No newline at end of file diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 6728c8a2e..b704bc185 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -29,24 +29,28 @@ use deltachat::qr_code_generator::get_securejoin_qr_svg; use num_traits::{FromPrimitive, ToPrimitive}; use rand::Rng; +use deltachat::accounts::Accounts; use deltachat::chat::{ChatId, ChatVisibility, MuteDuration, ProtectionStatus}; +use deltachat::chatlist::Chatlist; use deltachat::constants::DC_MSG_ID_LAST_SPECIAL; use deltachat::contact::{Contact, ContactId, Origin}; use deltachat::context::Context; use deltachat::ephemeral::Timer as EphemeralTimer; use deltachat::key::DcKey; +use deltachat::log::LogExt; use deltachat::message::MsgId; +use deltachat::provider::Provider; use deltachat::stock_str::StockMessage; use deltachat::webxdc::StatusUpdateSerial; use deltachat::*; -use deltachat::{accounts::Accounts, log::LogExt}; mod dc_array; mod lot; - mod string; -use self::string::*; -use deltachat::chatlist::Chatlist; + +use string::*; + +pub use lot::dc_lot_t; // as C lacks a good and portable error handling, // in general, the C Interface is forgiving wrt to bad parameters. @@ -59,9 +63,12 @@ use deltachat::chatlist::Chatlist; // TODO: constants // dc_context_t - +// +// This is newtyped so that cbindgen does not need to scan dependencies and so that we can +// have our own doc comment. /// Struct representing the deltachat context. -pub type dc_context_t = Context; +#[derive(Debug)] +pub struct dc_context_t(Context); #[no_mangle] pub unsafe extern "C" fn dc_context_new( @@ -85,7 +92,7 @@ pub unsafe extern "C" fn dc_context_new( return ptr::null_mut(); }; match ctx { - Ok(ctx) => Box::into_raw(Box::new(ctx)), + Ok(ctx) => Box::into_raw(Box::new(dc_context_t(ctx))), Err(err) => { eprintln!("failed to create context: {:#}", err); ptr::null_mut() @@ -107,7 +114,7 @@ pub unsafe extern "C" fn dc_context_new_closed(dbfile: *const libc::c_char) -> * as_path(dbfile).to_path_buf().into(), id, )) { - Ok(context) => Box::into_raw(Box::new(context)), + Ok(context) => Box::into_raw(Box::new(dc_context_t(context))), Err(err) => { eprintln!("failed to create context: {:#}", err); ptr::null_mut() @@ -125,7 +132,7 @@ pub unsafe extern "C" fn dc_context_open( return 0; } - let ctx = &*context; + let ctx = &(*context).0; let passphrase = to_string_lossy(passphrase); block_on(ctx.open(passphrase)) .log_err(ctx, "dc_context_open() failed") @@ -140,7 +147,7 @@ pub unsafe extern "C" fn dc_context_is_open(context: *mut dc_context_t) -> libc: return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(ctx.is_open()) as libc::c_int } @@ -162,7 +169,7 @@ pub unsafe extern "C" fn dc_get_blobdir(context: *mut dc_context_t) -> *mut libc eprintln!("ignoring careless call to dc_get_blobdir()"); return "".strdup(); } - let ctx = &*context; + let ctx = &(*context).0; ctx.get_blobdir().to_string_lossy().strdup() } @@ -176,7 +183,7 @@ pub unsafe extern "C" fn dc_set_config( eprintln!("ignoring careless call to dc_set_config()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; let key = to_string_lossy(key); let value = to_opt_string_lossy(value); @@ -213,7 +220,7 @@ pub unsafe extern "C" fn dc_get_config( eprintln!("ignoring careless call to dc_get_config()"); return "".strdup(); } - let ctx = &*context; + let ctx = &(*context).0; let key = to_string_lossy(key); @@ -254,7 +261,7 @@ pub unsafe extern "C" fn dc_set_stock_translation( return 0; } let msg = to_string_lossy(stock_msg); - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { match StockMessage::from_u32(stock_id) { @@ -283,7 +290,7 @@ pub unsafe extern "C" fn dc_set_config_from_qr( return 0; } let qr = to_string_lossy(qr); - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { match qr::set_config_from_qr(ctx, &qr).await { @@ -302,7 +309,7 @@ pub unsafe extern "C" fn dc_get_info(context: *const dc_context_t) -> *mut libc: eprintln!("ignoring careless call to dc_get_info()"); return "".strdup(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { match ctx.get_info().await { Ok(info) => render_info(info).unwrap_or_default().strdup(), @@ -331,7 +338,7 @@ pub unsafe extern "C" fn dc_get_connectivity(context: *const dc_context_t) -> li eprintln!("ignoring careless call to dc_get_connectivity()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ctx.get_connectivity().await as u32 as libc::c_int }) } @@ -343,7 +350,7 @@ pub unsafe extern "C" fn dc_get_connectivity_html( eprintln!("ignoring careless call to dc_get_connectivity_html()"); return "".strdup(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { match ctx.get_connectivity_html().await { Ok(html) => html.strdup(), @@ -361,7 +368,7 @@ pub unsafe extern "C" fn dc_all_work_done(context: *mut dc_context_t) -> libc::c eprintln!("ignoring careless call to dc_all_work_done()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ctx.all_work_done().await as libc::c_int }) } @@ -375,7 +382,7 @@ pub unsafe extern "C" fn dc_get_oauth2_url( eprintln!("ignoring careless call to dc_get_oauth2_url()"); return ptr::null_mut(); // NULL explicitly defined as "unknown" } - let ctx = &*context; + let ctx = &(*context).0; let addr = to_string_lossy(addr); let redirect = to_string_lossy(redirect); @@ -397,7 +404,7 @@ pub unsafe extern "C" fn dc_configure(context: *mut dc_context_t) { return; } - let ctx = &*context; + let ctx = &(*context).0; spawn(async move { ctx.configure().await.log_err(ctx, "Configure failed") }); } @@ -408,7 +415,7 @@ pub unsafe extern "C" fn dc_is_configured(context: *mut dc_context_t) -> libc::c eprintln!("ignoring careless call to dc_is_configured()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ctx.is_configured() @@ -423,7 +430,7 @@ pub unsafe extern "C" fn dc_start_io(context: *mut dc_context_t) { if context.is_null() { return; } - let ctx = &*context; + let ctx = &(*context).0; block_on(ctx.start_io()) } @@ -433,12 +440,12 @@ pub unsafe extern "C" fn dc_get_id(context: *mut dc_context_t) -> libc::c_int { if context.is_null() { return 0; } - let ctx = &*context; + let ctx = &(*context).0; ctx.get_id() as libc::c_int } -pub type dc_event_t = Event; +pub struct dc_event_t(Event); #[no_mangle] pub unsafe extern "C" fn dc_event_unref(a: *mut dc_event_t) { @@ -457,7 +464,7 @@ pub unsafe extern "C" fn dc_event_get_id(event: *mut dc_event_t) -> libc::c_int return 0; } - let event = &*event; + let event = &(*event).0; event.as_id() } @@ -468,7 +475,7 @@ pub unsafe extern "C" fn dc_event_get_data1_int(event: *mut dc_event_t) -> libc: return 0; } - let event = &(*event).typ; + let event = &(*event).0.typ; match event { EventType::Info(_) | EventType::SmtpConnected(_) @@ -514,7 +521,7 @@ pub unsafe extern "C" fn dc_event_get_data2_int(event: *mut dc_event_t) -> libc: return 0; } - let event = &(*event).typ; + let event = &(*event).0.typ; match event { EventType::Info(_) @@ -556,7 +563,7 @@ pub unsafe extern "C" fn dc_event_get_data2_str(event: *mut dc_event_t) -> *mut return ptr::null_mut(); } - let event = &(*event).typ; + let event = &(*event).0.typ; match event { EventType::Info(msg) @@ -610,10 +617,10 @@ pub unsafe extern "C" fn dc_event_get_account_id(event: *mut dc_event_t) -> u32 return 0; } - (*event).id + (*event).0.id } -pub type dc_event_emitter_t = EventEmitter; +pub struct dc_event_emitter_t(EventEmitter); #[no_mangle] pub unsafe extern "C" fn dc_get_event_emitter( @@ -623,8 +630,8 @@ pub unsafe extern "C" fn dc_get_event_emitter( eprintln!("ignoring careless call to dc_get_event_emitter()"); return ptr::null_mut(); } - let ctx = &*context; - Box::into_raw(Box::new(ctx.get_event_emitter())) + let ctx = &(*context).0; + Box::into_raw(Box::new(dc_event_emitter_t(ctx.get_event_emitter()))) } #[no_mangle] @@ -643,11 +650,11 @@ pub unsafe extern "C" fn dc_get_next_event(events: *mut dc_event_emitter_t) -> * eprintln!("ignoring careless call to dc_get_next_event()"); return ptr::null_mut(); } - let events = &*events; + let events = &(*events).0; events .recv_sync() - .map(|ev| Box::into_raw(Box::new(ev))) + .map(|ev| Box::into_raw(Box::new(dc_event_t(ev)))) .unwrap_or_else(ptr::null_mut) } @@ -657,7 +664,7 @@ pub unsafe extern "C" fn dc_stop_io(context: *mut dc_context_t) { eprintln!("ignoring careless call to dc_shutdown()"); return; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ctx.stop_io().await; @@ -670,7 +677,7 @@ pub unsafe extern "C" fn dc_maybe_network(context: *mut dc_context_t) { eprintln!("ignoring careless call to dc_maybe_network()"); return; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ctx.maybe_network().await }) } @@ -686,7 +693,7 @@ pub unsafe extern "C" fn dc_preconfigure_keypair( eprintln!("ignoring careless call to dc_preconfigure_keypair()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { let addr = dc_tools::EmailAddress::new(&to_string_lossy(addr))?; let public = key::SignedPublicKey::from_asc(&to_string_lossy(public_data))?.0; @@ -714,7 +721,7 @@ pub unsafe extern "C" fn dc_get_chatlist( eprintln!("ignoring careless call to dc_get_chatlist()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; let qs = to_opt_string_lossy(query_str); let qi = if query_id == 0 { @@ -729,7 +736,7 @@ pub unsafe extern "C" fn dc_get_chatlist( .log_err(ctx, "Failed to get chatlist") { Ok(list) => { - let ffi_list = ChatlistWrapper { context, list }; + let ffi_list = dc_chatlist_t { context, list }; Box::into_raw(Box::new(ffi_list)) } Err(_) => ptr::null_mut(), @@ -746,7 +753,7 @@ pub unsafe extern "C" fn dc_create_chat_by_contact_id( eprintln!("ignoring careless call to dc_create_chat_by_contact_id()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ChatId::create_for_contact(ctx, ContactId::new(contact_id)) @@ -766,7 +773,7 @@ pub unsafe extern "C" fn dc_get_chat_id_by_contact_id( eprintln!("ignoring careless call to dc_get_chat_id_by_contact_id()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ChatId::lookup_by_contact(ctx, ContactId::new(contact_id)) @@ -788,8 +795,8 @@ pub unsafe extern "C" fn dc_prepare_msg( eprintln!("ignoring careless call to dc_prepare_msg()"); return 0; } - let ctx = &mut *context; - let ffi_msg: &mut MessageWrapper = &mut *msg; + let ctx = &mut (*context).0; + let ffi_msg: &mut dc_msg_t = &mut *msg; block_on(async move { chat::prepare_msg(ctx, ChatId::new(chat_id), &mut ffi_msg.message) @@ -809,7 +816,7 @@ pub unsafe extern "C" fn dc_send_msg( eprintln!("ignoring careless call to dc_send_msg()"); return 0; } - let ctx = &mut *context; + let ctx = &mut (*context).0; let ffi_msg = &mut *msg; block_on(async move { @@ -830,7 +837,7 @@ pub unsafe extern "C" fn dc_send_msg_sync( eprintln!("ignoring careless call to dc_send_msg_sync()"); return 0; } - let ctx = &mut *context; + let ctx = &mut (*context).0; let ffi_msg = &mut *msg; block_on(async move { @@ -851,7 +858,7 @@ pub unsafe extern "C" fn dc_send_text_msg( eprintln!("ignoring careless call to dc_send_text_msg()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; let text_to_send = to_string_lossy(text_to_send); block_on(async move { @@ -871,7 +878,7 @@ pub unsafe extern "C" fn dc_send_videochat_invitation( eprintln!("ignoring careless call to dc_send_videochat_invitation()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { chat::send_videochat_invitation(ctx, ChatId::new(chat_id)) @@ -892,7 +899,7 @@ pub unsafe extern "C" fn dc_send_webxdc_status_update( eprintln!("ignoring careless call to dc_send_webxdc_status_update()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(ctx.send_webxdc_status_update( MsgId::new(msg_id), @@ -913,7 +920,7 @@ pub unsafe extern "C" fn dc_get_webxdc_status_updates( eprintln!("ignoring careless call to dc_get_webxdc_status_updates()"); return "".strdup(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(ctx.get_webxdc_status_updates( MsgId::new(msg_id), @@ -933,11 +940,11 @@ pub unsafe extern "C" fn dc_set_draft( eprintln!("ignoring careless call to dc_set_draft()"); return; } - let ctx = &*context; + let ctx = &(*context).0; let msg = if msg.is_null() { None } else { - let ffi_msg: &mut MessageWrapper = &mut *msg; + let ffi_msg: &mut dc_msg_t = &mut *msg; Some(&mut ffi_msg.message) }; @@ -959,11 +966,11 @@ pub unsafe extern "C" fn dc_add_device_msg( eprintln!("ignoring careless call to dc_add_device_msg()"); return 0; } - let ctx = &mut *context; + let ctx = &mut (*context).0; let msg = if msg.is_null() { None } else { - let ffi_msg: &mut MessageWrapper = &mut *msg; + let ffi_msg: &mut dc_msg_t = &mut *msg; Some(&mut ffi_msg.message) }; @@ -984,7 +991,7 @@ pub unsafe extern "C" fn dc_was_device_msg_ever_added( eprintln!("ignoring careless call to dc_was_device_msg_ever_added()"); return 0; } - let ctx = &mut *context; + let ctx = &mut (*context).0; block_on(async move { chat::was_device_msg_ever_added(ctx, &to_string_lossy(label)) @@ -999,12 +1006,12 @@ pub unsafe extern "C" fn dc_get_draft(context: *mut dc_context_t, chat_id: u32) eprintln!("ignoring careless call to dc_get_draft()"); return ptr::null_mut(); // NULL explicitly defined as "no draft" } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { match ChatId::new(chat_id).get_draft(ctx).await { Ok(Some(draft)) => { - let ffi_msg = MessageWrapper { + let ffi_msg = dc_msg_t { context, message: draft, }; @@ -1030,7 +1037,7 @@ pub unsafe extern "C" fn dc_get_chat_msgs( eprintln!("ignoring careless call to dc_get_chat_msgs()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; let marker_flag = if marker1before <= DC_MSG_ID_LAST_SPECIAL { None } else { @@ -1053,7 +1060,7 @@ pub unsafe extern "C" fn dc_get_msg_cnt(context: *mut dc_context_t, chat_id: u32 eprintln!("ignoring careless call to dc_get_msg_cnt()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ChatId::new(chat_id) @@ -1072,7 +1079,7 @@ pub unsafe extern "C" fn dc_get_fresh_msg_cnt( eprintln!("ignoring careless call to dc_get_fresh_msg_cnt()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ChatId::new(chat_id) @@ -1092,7 +1099,7 @@ pub unsafe extern "C" fn dc_estimate_deletion_cnt( eprintln!("ignoring careless call to dc_estimate_deletion_cnt()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { message::estimate_deletion_cnt(ctx, from_server != 0, seconds) .await @@ -1108,7 +1115,7 @@ pub unsafe extern "C" fn dc_get_fresh_msgs( eprintln!("ignoring careless call to dc_get_fresh_msgs()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { let arr = dc_array_t::from( @@ -1130,7 +1137,7 @@ pub unsafe extern "C" fn dc_marknoticed_chat(context: *mut dc_context_t, chat_id eprintln!("ignoring careless call to dc_marknoticed_chat()"); return; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { chat::marknoticed_chat(ctx, ChatId::new(chat_id)) @@ -1160,7 +1167,7 @@ pub unsafe extern "C" fn dc_get_chat_media( eprintln!("ignoring careless call to dc_get_chat_media()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; let msg_type = from_prim(msg_type).expect(&format!("invalid msg_type = {}", msg_type)); let or_msg_type2 = from_prim(or_msg_type2).expect(&format!("incorrect or_msg_type2 = {}", or_msg_type2)); @@ -1202,7 +1209,7 @@ pub unsafe extern "C" fn dc_get_next_media( chat::Direction::Forward }; - let ctx = &*context; + let ctx = &(*context).0; let msg_type = from_prim(msg_type).expect(&format!("invalid msg_type = {}", msg_type)); let or_msg_type2 = from_prim(or_msg_type2).expect(&format!("incorrect or_msg_type2 = {}", or_msg_type2)); @@ -1234,7 +1241,7 @@ pub unsafe extern "C" fn dc_set_chat_protection( eprintln!("ignoring careless call to dc_set_chat_protection()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; let protect = if let Some(s) = ProtectionStatus::from_i32(protect) { s } else { @@ -1260,7 +1267,7 @@ pub unsafe extern "C" fn dc_set_chat_visibility( eprintln!("ignoring careless call to dc_set_chat_visibility()"); return; } - let ctx = &*context; + let ctx = &(*context).0; let visibility = match archive { 0 => ChatVisibility::Normal, 1 => ChatVisibility::Archived, @@ -1289,7 +1296,7 @@ pub unsafe extern "C" fn dc_delete_chat(context: *mut dc_context_t, chat_id: u32 eprintln!("ignoring careless call to dc_delete_chat()"); return; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ChatId::new(chat_id) @@ -1305,7 +1312,7 @@ pub unsafe extern "C" fn dc_block_chat(context: *mut dc_context_t, chat_id: u32) eprintln!("ignoring careless call to dc_block_chat()"); return; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ChatId::new(chat_id) @@ -1321,7 +1328,7 @@ pub unsafe extern "C" fn dc_accept_chat(context: *mut dc_context_t, chat_id: u32 eprintln!("ignoring careless call to dc_accept_chat()"); return; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ChatId::new(chat_id) @@ -1340,7 +1347,7 @@ pub unsafe extern "C" fn dc_get_chat_contacts( eprintln!("ignoring careless call to dc_get_chat_contacts()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { let arr = dc_array_t::from( @@ -1365,7 +1372,7 @@ pub unsafe extern "C" fn dc_search_msgs( eprintln!("ignoring careless call to dc_search_msgs()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; let chat_id = if chat_id == 0 { None } else { @@ -1391,12 +1398,12 @@ pub unsafe extern "C" fn dc_get_chat(context: *mut dc_context_t, chat_id: u32) - eprintln!("ignoring careless call to dc_get_chat()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { match chat::Chat::load_from_db(ctx, ChatId::new(chat_id)).await { Ok(chat) => { - let ffi_chat = ChatWrapper { context, chat }; + let ffi_chat = dc_chat_t { context, chat }; Box::into_raw(Box::new(ffi_chat)) } Err(_) => ptr::null_mut(), @@ -1414,7 +1421,7 @@ pub unsafe extern "C" fn dc_create_group_chat( eprintln!("ignoring careless call to dc_create_group_chat()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; let protect = if let Some(s) = ProtectionStatus::from_i32(protect) { s } else { @@ -1437,7 +1444,7 @@ pub unsafe extern "C" fn dc_create_broadcast_list(context: *mut dc_context_t) -> eprintln!("ignoring careless call to dc_create_broadcast_list()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(chat::create_broadcast_list(ctx)) .log_err(ctx, "Failed to create broadcast list") .map(|id| id.to_u32()) @@ -1454,7 +1461,7 @@ pub unsafe extern "C" fn dc_is_contact_in_chat( eprintln!("ignoring careless call to dc_is_contact_in_chat()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(chat::is_contact_in_chat( ctx, @@ -1475,7 +1482,7 @@ pub unsafe extern "C" fn dc_add_contact_to_chat( eprintln!("ignoring careless call to dc_add_contact_to_chat()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(chat::add_contact_to_chat( ctx, @@ -1496,7 +1503,7 @@ pub unsafe extern "C" fn dc_remove_contact_from_chat( eprintln!("ignoring careless call to dc_remove_contact_from_chat()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(chat::remove_contact_from_chat( ctx, @@ -1518,7 +1525,7 @@ pub unsafe extern "C" fn dc_set_chat_name( eprintln!("ignoring careless call to dc_set_chat_name()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { chat::set_chat_name(ctx, ChatId::new(chat_id), &to_string_lossy(name)) @@ -1538,7 +1545,7 @@ pub unsafe extern "C" fn dc_set_chat_profile_image( eprintln!("ignoring careless call to dc_set_chat_profile_image()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { chat::set_chat_profile_image(ctx, ChatId::new(chat_id), to_string_lossy(image)) @@ -1558,7 +1565,7 @@ pub unsafe extern "C" fn dc_set_chat_mute_duration( eprintln!("ignoring careless call to dc_set_chat_mute_duration()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; let muteDuration = match duration { 0 => MuteDuration::NotMuted, -1 => MuteDuration::Forever, @@ -1591,7 +1598,7 @@ pub unsafe extern "C" fn dc_get_chat_encrinfo( eprintln!("ignoring careless call to dc_get_chat_encrinfo()"); return "".strdup(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ChatId::new(chat_id) @@ -1614,7 +1621,7 @@ pub unsafe extern "C" fn dc_get_chat_ephemeral_timer( eprintln!("ignoring careless call to dc_get_chat_ephemeral_timer()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; // Timer value 0 is returned in the rare case of a database error, // but it is not dangerous since it is only meant to be used as a @@ -1637,7 +1644,7 @@ pub unsafe extern "C" fn dc_set_chat_ephemeral_timer( eprintln!("ignoring careless call to dc_set_chat_ephemeral_timer()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { ChatId::new(chat_id) @@ -1657,7 +1664,7 @@ pub unsafe extern "C" fn dc_get_msg_info( eprintln!("ignoring careless call to dc_get_msg_info()"); return "".strdup(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { message::get_msg_info(ctx, MsgId::new(msg_id)) @@ -1676,7 +1683,7 @@ pub unsafe extern "C" fn dc_get_msg_html( eprintln!("ignoring careless call to dc_get_msg_html()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(MsgId::new(msg_id).get_html(ctx)) .unwrap_or_log_default(ctx, "Failed get_msg_html") @@ -1692,7 +1699,7 @@ pub unsafe extern "C" fn dc_get_mime_headers( eprintln!("ignoring careless call to dc_get_mime_headers()"); return ptr::null_mut(); // NULL explicitly defined as "no mime headers" } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { let mime = message::get_mime_headers(ctx, MsgId::new(msg_id)) @@ -1715,7 +1722,7 @@ pub unsafe extern "C" fn dc_delete_msgs( eprintln!("ignoring careless call to dc_delete_msgs()"); return; } - let ctx = &*context; + let ctx = &(*context).0; let msg_ids = convert_and_prune_message_ids(msg_ids, msg_cnt); block_on(message::delete_msgs(ctx, &msg_ids)) @@ -1739,7 +1746,7 @@ pub unsafe extern "C" fn dc_forward_msgs( return; } let msg_ids = convert_and_prune_message_ids(msg_ids, msg_cnt); - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { chat::forward_msgs(ctx, &msg_ids[..], ChatId::new(chat_id)) @@ -1759,7 +1766,7 @@ pub unsafe extern "C" fn dc_markseen_msgs( return; } let msg_ids = convert_and_prune_message_ids(msg_ids, msg_cnt); - let ctx = &*context; + let ctx = &(*context).0; block_on(message::markseen_msgs(ctx, msg_ids)) .log_err(ctx, "failed dc_markseen_msgs() call") @@ -1772,7 +1779,7 @@ pub unsafe extern "C" fn dc_get_msg(context: *mut dc_context_t, msg_id: u32) -> eprintln!("ignoring careless call to dc_get_msg()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { let message = match message::Message::load_from_db(ctx, MsgId::new(msg_id)).await { @@ -1794,7 +1801,7 @@ pub unsafe extern "C" fn dc_get_msg(context: *mut dc_context_t, msg_id: u32) -> } } }; - let ffi_msg = MessageWrapper { context, message }; + let ffi_msg = dc_msg_t { context, message }; Box::into_raw(Box::new(ffi_msg)) }) } @@ -1805,7 +1812,7 @@ pub unsafe extern "C" fn dc_download_full_msg(context: *mut dc_context_t, msg_id eprintln!("ignoring careless call to dc_download_full_msg()"); return; } - let ctx = &*context; + let ctx = &(*context).0; block_on(MsgId::new(msg_id).download_full(ctx)) .log_err(ctx, "Failed to download message fully.") .ok(); @@ -1830,7 +1837,7 @@ pub unsafe extern "C" fn dc_lookup_contact_id_by_addr( eprintln!("ignoring careless call to dc_lookup_contact_id_by_addr()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { Contact::lookup_id_by_addr(ctx, &to_string_lossy(addr), Origin::IncomingReplyTo) @@ -1851,7 +1858,7 @@ pub unsafe extern "C" fn dc_create_contact( eprintln!("ignoring careless call to dc_create_contact()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; let name = to_string_lossy(name); block_on(async move { @@ -1871,7 +1878,7 @@ pub unsafe extern "C" fn dc_add_address_book( eprintln!("ignoring careless call to dc_add_address_book()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { match Contact::add_address_book(ctx, &to_string_lossy(addr_book)).await { @@ -1891,7 +1898,7 @@ pub unsafe extern "C" fn dc_get_contacts( eprintln!("ignoring careless call to dc_get_contacts()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; let query = to_opt_string_lossy(query); block_on(async move { @@ -1910,7 +1917,7 @@ pub unsafe extern "C" fn dc_get_blocked_cnt(context: *mut dc_context_t) -> libc: eprintln!("ignoring careless call to dc_get_blocked_cnt()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { Contact::get_all_blocked(ctx) @@ -1928,7 +1935,7 @@ pub unsafe extern "C" fn dc_get_blocked_contacts( eprintln!("ignoring careless call to dc_get_blocked_contacts()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { Box::into_raw(Box::new(dc_array_t::from( @@ -1953,7 +1960,7 @@ pub unsafe extern "C" fn dc_block_contact( eprintln!("ignoring careless call to dc_block_contact()"); return; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { if block == 0 { Contact::unblock(ctx, ContactId::new(contact_id)) @@ -1976,7 +1983,7 @@ pub unsafe extern "C" fn dc_get_contact_encrinfo( eprintln!("ignoring careless call to dc_get_contact_encrinfo()"); return "".strdup(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { Contact::get_encrinfo(ctx, ContactId::new(contact_id)) @@ -1998,7 +2005,7 @@ pub unsafe extern "C" fn dc_delete_contact( eprintln!("ignoring careless call to dc_delete_contact()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { match Contact::delete(ctx, ContactId::new(contact_id)).await { @@ -2017,12 +2024,12 @@ pub unsafe extern "C" fn dc_get_contact( eprintln!("ignoring careless call to dc_get_contact()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { Contact::get_by_id(ctx, ContactId::new(contact_id)) .await - .map(|contact| Box::into_raw(Box::new(ContactWrapper { context, contact }))) + .map(|contact| Box::into_raw(Box::new(dc_contact_t { context, contact }))) .unwrap_or_else(|_| ptr::null_mut()) }) } @@ -2047,7 +2054,7 @@ pub unsafe extern "C" fn dc_imex( }; let passphrase = to_opt_string_lossy(param2); - let ctx = &*context; + let ctx = &(*context).0; if let Some(param1) = to_opt_string_lossy(param1) { spawn(async move { @@ -2069,7 +2076,7 @@ pub unsafe extern "C" fn dc_imex_has_backup( eprintln!("ignoring careless call to dc_imex_has_backup()"); return ptr::null_mut(); // NULL explicitly defined as "has no backup" } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { match imex::has_backup(ctx, to_string_lossy(dir).as_ref()).await { @@ -2090,7 +2097,7 @@ pub unsafe extern "C" fn dc_initiate_key_transfer(context: *mut dc_context_t) -> eprintln!("ignoring careless call to dc_initiate_key_transfer()"); return ptr::null_mut(); // NULL explicitly defined as "error" } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { match imex::initiate_key_transfer(ctx).await { @@ -2116,7 +2123,7 @@ pub unsafe extern "C" fn dc_continue_key_transfer( eprintln!("ignoring careless call to dc_continue_key_transfer()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { match imex::continue_key_transfer(ctx, MsgId::new(msg_id), &to_string_lossy(setup_code)) @@ -2137,7 +2144,7 @@ pub unsafe extern "C" fn dc_stop_ongoing_process(context: *mut dc_context_t) { eprintln!("ignoring careless call to dc_stop_ongoing_process()"); return; } - let ctx = &*context; + let ctx = &(*context).0; block_on(ctx.stop_ongoing()); } @@ -2150,7 +2157,7 @@ pub unsafe extern "C" fn dc_check_qr( eprintln!("ignoring careless call to dc_check_qr()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; let lot = match block_on(qr::check_qr(ctx, &to_string_lossy(qr))) { Ok(qr) => qr.into(), @@ -2168,7 +2175,7 @@ pub unsafe extern "C" fn dc_get_securejoin_qr( eprintln!("ignoring careless call to dc_get_securejoin_qr()"); return "".strdup(); } - let ctx = &*context; + let ctx = &(*context).0; let chat_id = if chat_id == 0 { None } else { @@ -2189,7 +2196,7 @@ pub unsafe extern "C" fn dc_get_securejoin_qr_svg( eprintln!("ignoring careless call to generate_verification_qr()"); return "".strdup(); } - let ctx = &*context; + let ctx = &(*context).0; let chat_id = if chat_id == 0 { None } else { @@ -2210,7 +2217,7 @@ pub unsafe extern "C" fn dc_join_securejoin( eprintln!("ignoring careless call to dc_join_securejoin()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { securejoin::dc_join_securejoin(ctx, &to_string_lossy(qr)) @@ -2231,7 +2238,7 @@ pub unsafe extern "C" fn dc_send_locations_to_chat( eprintln!("ignoring careless call to dc_send_locations_to_chat()"); return; } - let ctx = &*context; + let ctx = &(*context).0; block_on(location::send_locations_to_chat( ctx, @@ -2251,7 +2258,7 @@ pub unsafe extern "C" fn dc_is_sending_locations_to_chat( eprintln!("ignoring careless call to dc_is_sending_locations_to_chat()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; let chat_id = if chat_id == 0 { None } else { @@ -2273,7 +2280,7 @@ pub unsafe extern "C" fn dc_set_location( eprintln!("ignoring careless call to dc_set_location()"); return 0; } - let ctx = &*context; + let ctx = &(*context).0; block_on(location::set(ctx, latitude, longitude, accuracy)) as _ } @@ -2290,7 +2297,7 @@ pub unsafe extern "C" fn dc_get_locations( eprintln!("ignoring careless call to dc_get_locations()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; let chat_id = if chat_id == 0 { None } else { @@ -2322,7 +2329,7 @@ pub unsafe extern "C" fn dc_delete_all_locations(context: *mut dc_context_t) { eprintln!("ignoring careless call to dc_delete_all_locations()"); return; } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { location::delete_all(ctx) @@ -2338,7 +2345,7 @@ pub unsafe extern "C" fn dc_get_last_error(context: *mut dc_context_t) -> *mut l eprintln!("ignoring careless call to dc_get_last_error()"); return "".strdup(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(ctx.get_last_error()).strdup() } @@ -2514,20 +2521,18 @@ pub unsafe fn dc_array_is_independent( // dc_chatlist_t -/// FFI struct for [dc_chatlist_t] -/// -/// This is the structure behind [dc_chatlist_t] which is the opaque -/// structure representing a chatlist in the FFI API. It exists -/// because the FFI API has a refernce from the message to the -/// context, but the Rust API does not, so the FFI layer needs to glue -/// these together. -pub struct ChatlistWrapper { +// FFI struct for [dc_chatlist_t] +// +// This is the structure behind [dc_chatlist_t] which is the opaque +// structure representing a chatlist in the FFI API. It exists +// because the FFI API has a refernce from the message to the +// context, but the Rust API does not, so the FFI layer needs to glue +// these together. +pub struct dc_chatlist_t { context: *const dc_context_t, list: chatlist::Chatlist, } -pub type dc_chatlist_t = ChatlistWrapper; - #[no_mangle] pub unsafe extern "C" fn dc_chatlist_unref(chatlist: *mut dc_chatlist_t) { if chatlist.is_null() { @@ -2557,7 +2562,7 @@ pub unsafe extern "C" fn dc_chatlist_get_chat_id( return 0; } let ffi_list = &*chatlist; - let ctx = &*ffi_list.context; + let ctx = &(*ffi_list.context).0; match ffi_list.list.get_chat_id(index as usize) { Ok(chat_id) => chat_id.to_u32(), Err(err) => { @@ -2577,7 +2582,7 @@ pub unsafe extern "C" fn dc_chatlist_get_msg_id( return 0; } let ffi_list = &*chatlist; - let ctx = &*ffi_list.context; + let ctx = &(*ffi_list.context).0; match ffi_list.list.get_msg_id(index as usize) { Ok(msg_id) => msg_id.map_or(0, |msg_id| msg_id.to_u32()), Err(err) => { @@ -2604,7 +2609,7 @@ pub unsafe extern "C" fn dc_chatlist_get_summary( Some(&ffi_chat.chat) }; let ffi_list = &*chatlist; - let ctx = &*ffi_list.context; + let ctx = &(*ffi_list.context).0; block_on(async move { let summary = ffi_list @@ -2627,7 +2632,7 @@ pub unsafe extern "C" fn dc_chatlist_get_summary2( eprintln!("ignoring careless call to dc_chatlist_get_summary2()"); return ptr::null_mut(); } - let ctx = &*context; + let ctx = &(*context).0; let msg_id = if msg_id == 0 { None } else { @@ -2658,20 +2663,18 @@ pub unsafe extern "C" fn dc_chatlist_get_context( // dc_chat_t -/// FFI struct for [dc_chat_t] -/// -/// This is the structure behind [dc_chat_t] which is the opaque -/// structure representing a chat in the FFI API. It exists -/// because the FFI API has a refernce from the message to the -/// context, but the Rust API does not, so the FFI layer needs to glue -/// these together. -pub struct ChatWrapper { +// FFI struct for [dc_chat_t] +// +// This is the structure behind [dc_chat_t] which is the opaque +// structure representing a chat in the FFI API. It exists +// because the FFI API has a refernce from the message to the +// context, but the Rust API does not, so the FFI layer needs to glue +// these together. +pub struct dc_chat_t { context: *const dc_context_t, chat: chat::Chat, } -pub type dc_chat_t = ChatWrapper; - #[no_mangle] pub unsafe extern "C" fn dc_chat_unref(chat: *mut dc_chat_t) { if chat.is_null() { @@ -2719,7 +2722,7 @@ pub unsafe extern "C" fn dc_chat_get_profile_image(chat: *mut dc_chat_t) -> *mut return ptr::null_mut(); // NULL explicitly defined as "no image" } let ffi_chat = &*chat; - let ctx = &*ffi_chat.context; + let ctx = &(*ffi_chat.context).0; block_on(async move { match ffi_chat.chat.get_profile_image(ctx).await { @@ -2740,7 +2743,7 @@ pub unsafe extern "C" fn dc_chat_get_color(chat: *mut dc_chat_t) -> u32 { return 0; } let ffi_chat = &*chat; - let ctx = &*ffi_chat.context; + let ctx = &(*ffi_chat.context).0; block_on(ffi_chat.chat.get_color(ctx)).unwrap_or_log_default(ctx, "Failed get_color") } @@ -2806,7 +2809,7 @@ pub unsafe extern "C" fn dc_chat_can_send(chat: *mut dc_chat_t) -> libc::c_int { return 0; } let ffi_chat = &*chat; - let ctx = &*ffi_chat.context; + let ctx = &(*ffi_chat.context).0; block_on(ffi_chat.chat.can_send(ctx)) .log_err(ctx, "can_send failed") .unwrap_or_default() as libc::c_int @@ -2872,7 +2875,7 @@ pub unsafe extern "C" fn dc_chat_get_info_json( eprintln!("ignoring careless call to dc_chat_get_info_json()"); return "".strdup(); } - let ctx = &*context; + let ctx = &(*context).0; block_on(async move { let chat = match chat::Chat::load_from_db(ctx, ChatId::new(chat_id)).await { @@ -2900,20 +2903,18 @@ pub unsafe extern "C" fn dc_chat_get_info_json( // dc_msg_t -/// FFI struct for [dc_msg_t] -/// -/// This is the structure behind [dc_msg_t] which is the opaque -/// structure representing a message in the FFI API. It exists -/// because the FFI API has a refernce from the message to the -/// context, but the Rust API does not, so the FFI layer needs to glue -/// these together. -pub struct MessageWrapper { +// FFI struct for [dc_msg_t] +// +// This is the structure behind [dc_msg_t] which is the opaque +// structure representing a message in the FFI API. It exists +// because the FFI API has a refernce from the message to the +// context, but the Rust API does not, so the FFI layer needs to glue +// these together. +pub struct dc_msg_t { context: *const dc_context_t, message: message::Message, } -pub type dc_msg_t = MessageWrapper; - #[no_mangle] pub unsafe extern "C" fn dc_msg_new( context: *mut dc_context_t, @@ -2923,9 +2924,8 @@ pub unsafe extern "C" fn dc_msg_new( eprintln!("ignoring careless call to dc_msg_new()"); return ptr::null_mut(); } - let context = &*context; let viewtype = from_prim(viewtype).expect(&format!("invalid viewtype = {}", viewtype)); - let msg = MessageWrapper { + let msg = dc_msg_t { context, message: message::Message::new(viewtype), }; @@ -3063,7 +3063,7 @@ pub unsafe extern "C" fn dc_msg_get_file(msg: *mut dc_msg_t) -> *mut libc::c_cha return "".strdup(); } let ffi_msg = &*msg; - let ctx = &*ffi_msg.context; + let ctx = &(*ffi_msg.context).0; ffi_msg .message .get_file(ctx) @@ -3092,7 +3092,7 @@ pub unsafe extern "C" fn dc_msg_get_webxdc_blob( return ptr::null_mut(); } let ffi_msg = &*msg; - let ctx = &*ffi_msg.context; + let ctx = &(*ffi_msg.context).0; let blob = block_on(async move { ffi_msg .message @@ -3120,7 +3120,7 @@ pub unsafe extern "C" fn dc_msg_get_webxdc_info(msg: *mut dc_msg_t) -> *mut libc return "".strdup(); } let ffi_msg = &*msg; - let ctx = &*ffi_msg.context; + let ctx = &(*ffi_msg.context).0; block_on(async move { let info = match ffi_msg.message.get_webxdc_info(ctx).await { @@ -3157,7 +3157,7 @@ pub unsafe extern "C" fn dc_msg_get_filebytes(msg: *mut dc_msg_t) -> u64 { return 0; } let ffi_msg = &*msg; - let ctx = &*ffi_msg.context; + let ctx = &(*ffi_msg.context).0; block_on(ffi_msg.message.get_filebytes(ctx)) } @@ -3248,7 +3248,7 @@ pub unsafe extern "C" fn dc_msg_get_summary( Some(&ffi_chat.chat) }; let ffi_msg = &mut *msg; - let ctx = &*ffi_msg.context; + let ctx = &(*ffi_msg.context).0; let summary = block_on(ffi_msg.message.get_summary(ctx, maybe_chat)) .log_err(ctx, "dc_msg_get_summary failed") @@ -3266,7 +3266,7 @@ pub unsafe extern "C" fn dc_msg_get_summarytext( return "".strdup(); } let ffi_msg = &mut *msg; - let ctx = &*ffi_msg.context; + let ctx = &(*ffi_msg.context).0; let summary = block_on(ffi_msg.message.get_summary(ctx, None)) .log_err(ctx, "dc_msg_get_summarytext failed") @@ -3410,7 +3410,7 @@ pub unsafe extern "C" fn dc_msg_get_setupcodebegin(msg: *mut dc_msg_t) -> *mut l return "".strdup(); } let ffi_msg = &*msg; - let ctx = &*ffi_msg.context; + let ctx = &(*ffi_msg.context).0; block_on(ffi_msg.message.get_setupcodebegin(ctx)) .unwrap_or_default() @@ -3519,7 +3519,7 @@ pub unsafe extern "C" fn dc_msg_latefiling_mediasize( return; } let ffi_msg = &mut *msg; - let ctx = &*ffi_msg.context; + let ctx = &(*ffi_msg.context).0; block_on({ ffi_msg @@ -3559,12 +3559,13 @@ pub unsafe extern "C" fn dc_msg_set_quote(msg: *mut dc_msg_t, quote: *const dc_m Some(&ffi_quote.message) }; + let ctx = &(*ffi_msg.context).0; block_on(async move { ffi_msg .message - .set_quote(&*ffi_msg.context, quote_msg) + .set_quote(ctx, quote_msg) .await - .log_err(&*ffi_msg.context, "failed to set quote") + .log_err(ctx, "failed to set quote") .ok(); }); } @@ -3575,7 +3576,7 @@ pub unsafe extern "C" fn dc_msg_get_quoted_text(msg: *const dc_msg_t) -> *mut li eprintln!("ignoring careless call to dc_msg_get_quoted_text()"); return ptr::null_mut(); } - let ffi_msg: &MessageWrapper = &*msg; + let ffi_msg: &dc_msg_t = &*msg; ffi_msg .message .quoted_text() @@ -3588,8 +3589,8 @@ pub unsafe extern "C" fn dc_msg_get_quoted_msg(msg: *const dc_msg_t) -> *mut dc_ eprintln!("ignoring careless call to dc_get_quoted_msg()"); return ptr::null_mut(); } - let ffi_msg: &MessageWrapper = &*msg; - let context = &*ffi_msg.context; + let ffi_msg: &dc_msg_t = &*msg; + let context = &(*ffi_msg.context).0; let res = block_on(async move { ffi_msg .message @@ -3600,7 +3601,10 @@ pub unsafe extern "C" fn dc_msg_get_quoted_msg(msg: *const dc_msg_t) -> *mut dc_ }); match res { - Some(message) => Box::into_raw(Box::new(MessageWrapper { context, message })), + Some(message) => Box::into_raw(Box::new(dc_msg_t { + context: ffi_msg.context, + message, + })), None => ptr::null_mut(), } } @@ -3611,8 +3615,8 @@ pub unsafe extern "C" fn dc_msg_get_parent(msg: *const dc_msg_t) -> *mut dc_msg_ eprintln!("ignoring careless call to dc_msg_get_parent()"); return ptr::null_mut(); } - let ffi_msg: &MessageWrapper = &*msg; - let context = &*ffi_msg.context; + let ffi_msg: &dc_msg_t = &*msg; + let context = &(*ffi_msg.context).0; let res = block_on(async move { ffi_msg .message @@ -3623,7 +3627,10 @@ pub unsafe extern "C" fn dc_msg_get_parent(msg: *const dc_msg_t) -> *mut dc_msg_ }); match res { - Some(message) => Box::into_raw(Box::new(MessageWrapper { context, message })), + Some(message) => Box::into_raw(Box::new(dc_msg_t { + context: ffi_msg.context, + message, + })), None => ptr::null_mut(), } } @@ -3640,20 +3647,18 @@ pub unsafe extern "C" fn dc_msg_force_plaintext(msg: *mut dc_msg_t) { // dc_contact_t -/// FFI struct for [dc_contact_t] -/// -/// This is the structure behind [dc_contact_t] which is the opaque -/// structure representing a contact in the FFI API. It exists -/// because the FFI API has a refernce from the message to the -/// context, but the Rust API does not, so the FFI layer needs to glue -/// these together. -pub struct ContactWrapper { +// FFI struct for [dc_contact_t] +// +// This is the structure behind [dc_contact_t] which is the opaque +// structure representing a contact in the FFI API. It exists +// because the FFI API has a refernce from the message to the +// context, but the Rust API does not, so the FFI layer needs to glue +// these together. +pub struct dc_contact_t { context: *const dc_context_t, contact: contact::Contact, } -pub type dc_contact_t = ContactWrapper; - #[no_mangle] pub unsafe extern "C" fn dc_contact_unref(contact: *mut dc_contact_t) { if contact.is_null() { @@ -3736,7 +3741,7 @@ pub unsafe extern "C" fn dc_contact_get_profile_image( return ptr::null_mut(); // NULL explicitly defined as "no profile image" } let ffi_contact = &*contact; - let ctx = &*ffi_contact.context; + let ctx = &(*ffi_contact.context).0; block_on(async move { ffi_contact @@ -3796,7 +3801,7 @@ pub unsafe extern "C" fn dc_contact_is_verified(contact: *mut dc_contact_t) -> l return 0; } let ffi_contact = &*contact; - let ctx = &*ffi_contact.context; + let ctx = &(*ffi_contact.context).0; block_on(ffi_contact.contact.is_verified(ctx)) .log_err(ctx, "is_verified failed") @@ -3805,8 +3810,6 @@ pub unsafe extern "C" fn dc_contact_is_verified(contact: *mut dc_contact_t) -> l // dc_lot_t -pub type dc_lot_t = lot::Lot; - #[no_mangle] pub unsafe extern "C" fn dc_lot_unref(lot: *mut dc_lot_t) { if lot.is_null() { @@ -3934,7 +3937,9 @@ fn convert_and_prune_message_ids(msg_ids: *const u32, msg_cnt: libc::c_int) -> V // dc_provider_t -pub type dc_provider_t = provider::Provider; +// We have no newtype for this since we must give out 'static pointers. Instead +// cbindgen.toml does this rename, and we include a local alias for clarity. +type dc_provider_t = Provider; #[no_mangle] pub unsafe extern "C" fn dc_provider_new_from_email( @@ -3947,7 +3952,7 @@ pub unsafe extern "C" fn dc_provider_new_from_email( } let addr = to_string_lossy(addr); - let ctx = &*context; + let ctx = &(*context).0; let socks5_enabled = block_on(async move { ctx.get_config_bool(config::Config::Socks5Enabled) .await @@ -4016,13 +4021,14 @@ pub unsafe extern "C" fn dc_provider_unref(provider: *mut dc_provider_t) { // -- Accounts -/// Reader-writer lock wrapper for accounts manager to guarantee thread safety when using -/// `dc_accounts_t` in multiple threads at once. -pub struct AccountsWrapper { +// Reader-writer lock wrapper for accounts manager to guarantee thread safety when using +// `dc_accounts_t` in multiple threads at once. +/// Struct representing a list of deltachat accounts. +pub struct dc_accounts_t { inner: RwLock, } -impl Deref for AccountsWrapper { +impl Deref for dc_accounts_t { type Target = RwLock; fn deref(&self) -> &Self::Target { @@ -4030,15 +4036,15 @@ impl Deref for AccountsWrapper { } } -impl AccountsWrapper { +impl dc_accounts_t { fn new(accounts: Accounts) -> Self { let inner = RwLock::new(accounts); Self { inner } } } -/// Struct representing a list of deltachat accounts. -pub type dc_accounts_t = AccountsWrapper; +// /// Struct representing a list of deltachat accounts. +// pub type dc_accounts_t = dc_accounts_t; #[no_mangle] pub unsafe extern "C" fn dc_accounts_new( @@ -4055,7 +4061,7 @@ pub unsafe extern "C" fn dc_accounts_new( let accs = block_on(Accounts::new(as_path(dbfile).to_path_buf().into())); match accs { - Ok(accs) => Box::into_raw(Box::new(AccountsWrapper::new(accs))), + Ok(accs) => Box::into_raw(Box::new(dc_accounts_t::new(accs))), Err(err) => { // We are using Anyhow's .context() and to show the inner error, too, we need the {:#}: eprintln!("failed to create accounts: {:#}", err); @@ -4088,7 +4094,7 @@ pub unsafe extern "C" fn dc_accounts_get_account( let accounts = &*accounts; block_on(async move { accounts.read().await.get_account(id).await }) - .map(|ctx| Box::into_raw(Box::new(ctx))) + .map(|ctx| Box::into_raw(Box::new(dc_context_t(ctx)))) .unwrap_or_else(std::ptr::null_mut) } @@ -4103,7 +4109,7 @@ pub unsafe extern "C" fn dc_accounts_get_selected_account( let accounts = &*accounts; block_on(async move { accounts.read().await.get_selected_account().await }) - .map(|ctx| Box::into_raw(Box::new(ctx))) + .map(|ctx| Box::into_raw(Box::new(dc_context_t(ctx)))) .unwrap_or_else(std::ptr::null_mut) } @@ -4307,7 +4313,7 @@ pub unsafe extern "C" fn dc_accounts_maybe_network_lost(accounts: *mut dc_accoun block_on(async move { accounts.write().await.maybe_network_lost().await }); } -pub type dc_accounts_event_emitter_t = deltachat::accounts::EventEmitter; +pub struct dc_accounts_event_emitter_t(deltachat::accounts::EventEmitter); #[no_mangle] pub unsafe extern "C" fn dc_accounts_get_event_emitter( @@ -4321,7 +4327,7 @@ pub unsafe extern "C" fn dc_accounts_get_event_emitter( let accounts = &*accounts; let emitter = block_on(async move { accounts.read().await.get_event_emitter().await }); - Box::into_raw(Box::new(emitter)) + Box::into_raw(Box::new(dc_accounts_event_emitter_t(emitter))) } #[no_mangle] @@ -4343,10 +4349,17 @@ pub unsafe extern "C" fn dc_accounts_get_next_event( eprintln!("ignoring careless call to dc_accounts_get_next_event()"); return ptr::null_mut(); } - let emitter = &mut *emitter; + let emitter = &mut (*emitter).0; emitter .recv_sync() - .map(|ev| Box::into_raw(Box::new(ev))) + .map(|ev| Box::into_raw(Box::new(dc_event_t(ev)))) .unwrap_or_else(ptr::null_mut) } + +// pub const DC_CONNECTIVITY_NOT_CONNECTED: u32 = 1000; +pub const DC_CONNECTIVITY_NOT_CONNECTED: u32 = + deltachat::scheduler::connectivity::Connectivity::NotConnected as u32; +pub const DC_CONNECTIVITY_CONNECTING: u32 = 2000; +pub const DC_CONNECTIVITY_WORKING: u32 = 3000; +pub const DC_CONNECTIVITY_CONNECTED: u32 = 4000; diff --git a/deltachat-ffi/src/lot.rs b/deltachat-ffi/src/lot.rs index 9426ef425..9938c9315 100644 --- a/deltachat-ffi/src/lot.rs +++ b/deltachat-ffi/src/lot.rs @@ -13,7 +13,7 @@ use std::borrow::Cow; /// /// *Lot* is used in the meaning *heap* here. #[derive(Debug)] -pub enum Lot { +pub enum dc_lot_t { Summary(Summary), Qr(Qr), Error(String), @@ -34,7 +34,7 @@ impl Default for Meaning { } } -impl Lot { +impl dc_lot_t { pub fn get_text1(&self) -> Option<&str> { match self { Self::Summary(summary) => match &summary.prefix { @@ -225,21 +225,21 @@ impl From for LotState { } } -impl From for Lot { +impl From for dc_lot_t { fn from(summary: Summary) -> Self { - Lot::Summary(summary) + dc_lot_t::Summary(summary) } } -impl From for Lot { +impl From for dc_lot_t { fn from(qr: Qr) -> Self { - Lot::Qr(qr) + dc_lot_t::Qr(qr) } } // Make it easy to convert errors into the final `Lot`. -impl From for Lot { +impl From for dc_lot_t { fn from(error: Error) -> Self { - Lot::Error(error.to_string()) + dc_lot_t::Error(error.to_string()) } } diff --git a/src/lib.rs b/src/lib.rs index 62214f21e..f8e8b468d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,7 +62,7 @@ mod e2ee; pub mod ephemeral; mod imap; pub mod imex; -mod scheduler; +pub mod scheduler; #[macro_use] mod job; mod format_flowed; diff --git a/src/scheduler.rs b/src/scheduler.rs index fd4f044d2..a15e33dfd 100644 --- a/src/scheduler.rs +++ b/src/scheduler.rs @@ -16,7 +16,7 @@ use crate::smtp::{send_smtp_messages, Smtp}; use self::connectivity::ConnectivityStore; -pub(crate) mod connectivity; +pub mod connectivity; pub(crate) struct StopToken; diff --git a/src/scheduler/connectivity.rs b/src/scheduler/connectivity.rs index 513f8bc33..03896459b 100644 --- a/src/scheduler/connectivity.rs +++ b/src/scheduler/connectivity.rs @@ -14,7 +14,7 @@ use crate::{context::Context, log::LogExt}; use anyhow::{anyhow, Result}; use humansize::{file_size_opts, FileSize}; -#[derive(Debug, Clone, Copy, PartialEq, Eq, EnumProperty, PartialOrd, Ord)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum Connectivity { NotConnected = 1000, Connecting = 2000, @@ -27,7 +27,7 @@ pub enum Connectivity { // the top) take priority. This means that e.g. if any folder has an error - usually // because there is no internet connection - the connectivity for the whole // account will be `Notconnected`. -#[derive(Debug, Clone, PartialEq, Eq, EnumProperty, PartialOrd)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)] enum DetailedConnectivity { Error(String), Uninitialized,