chatlist: resultify get_msg_id, get_summary and get_summary2

Avoid using MsgId::new(0) in place of `None` in the Rust part.
Zero ID is only used in FFI part now.
This commit is contained in:
link2xt
2021-06-26 16:12:28 +03:00
parent ad266fe82f
commit 8ce9a78d6c
8 changed files with 74 additions and 61 deletions

View File

@@ -2318,11 +2318,14 @@ pub unsafe extern "C" fn dc_chatlist_get_msg_id(
return 0;
}
let ffi_list = &*chatlist;
ffi_list
.list
.get_msg_id(index as usize)
.map(|msg_id| msg_id.to_u32())
.unwrap_or(0)
let ctx = &*ffi_list.context;
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) => {
warn!(ctx, "get_msg_id failed: {}", err);
0
}
}
}
#[no_mangle]
@@ -2348,7 +2351,9 @@ pub unsafe extern "C" fn dc_chatlist_get_summary(
let lot = ffi_list
.list
.get_summary(&ctx, index as usize, maybe_chat)
.await;
.await
.log_err(ctx, "get_summary failed")
.unwrap_or_default();
Box::into_raw(Box::new(lot))
})
}
@@ -2364,9 +2369,16 @@ pub unsafe extern "C" fn dc_chatlist_get_summary2(
return ptr::null_mut();
}
let ctx = &*context;
let msg_id = if msg_id == 0 {
None
} else {
Some(MsgId::new(msg_id))
};
block_on(async move {
let lot =
Chatlist::get_summary2(&ctx, ChatId::new(chat_id), MsgId::new(msg_id), None).await;
let lot = Chatlist::get_summary2(&ctx, ChatId::new(chat_id), msg_id, None)
.await
.log_err(ctx, "get_summary2 failed")
.unwrap_or_default();
Box::into_raw(Box::new(lot))
})
}

View File

@@ -551,7 +551,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
},
if chat.is_protected() { "🛡️" } else { "" },
);
let lot = chatlist.get_summary(&context, i, Some(&chat)).await;
let lot = chatlist.get_summary(&context, i, Some(&chat)).await?;
let statestr = if chat.visibility == ChatVisibility::Archived {
" [Archived]"
} else {

View File

@@ -86,7 +86,7 @@ async fn main() {
let chats = Chatlist::try_load(&ctx, 0, None, None).await.unwrap();
for i in 0..chats.len() {
let msg = Message::load_from_db(&ctx, chats.get_msg_id(i).unwrap())
let msg = Message::load_from_db(&ctx, chats.get_msg_id(i).unwrap().unwrap())
.await
.unwrap();
log::info!("[{}] msg: {:?}", i, msg);

View File

@@ -42,7 +42,7 @@ use crate::stock_str;
#[derive(Debug)]
pub struct Chatlist {
/// Stores pairs of `chat_id, message_id`
ids: Vec<(ChatId, MsgId)>,
ids: Vec<(ChatId, Option<MsgId>)>,
}
impl Chatlist {
@@ -111,7 +111,7 @@ impl Chatlist {
let process_row = |row: &rusqlite::Row| {
let chat_id: ChatId = row.get(0)?;
let msg_id: MsgId = row.get(1).unwrap_or_default();
let msg_id: Option<MsgId> = row.get(1)?;
Ok((chat_id, msg_id))
};
@@ -261,7 +261,7 @@ impl Chatlist {
get_last_deaddrop_fresh_msg(context).await?
{
if !flag_for_forwarding {
ids.insert(0, (DC_CHAT_ID_DEADDROP, last_deaddrop_fresh_msg_id));
ids.insert(0, (DC_CHAT_ID_DEADDROP, Some(last_deaddrop_fresh_msg_id)));
}
}
add_archived_link_item = true;
@@ -271,9 +271,9 @@ impl Chatlist {
if add_archived_link_item && dc_get_archived_cnt(context).await? > 0 {
if ids.is_empty() && flag_add_alldone_hint {
ids.push((DC_CHAT_ID_ALLDONE_HINT, MsgId::new(0)));
ids.push((DC_CHAT_ID_ALLDONE_HINT, None));
}
ids.push((DC_CHAT_ID_ARCHIVED_LINK, MsgId::new(0)));
ids.push((DC_CHAT_ID_ARCHIVED_LINK, None));
}
Ok(Chatlist { ids })
@@ -302,7 +302,7 @@ impl Chatlist {
/// Get a single message ID of a chatlist.
///
/// To get the message object from the message ID, use dc_get_msg().
pub fn get_msg_id(&self, index: usize) -> Result<MsgId> {
pub fn get_msg_id(&self, index: usize) -> Result<Option<MsgId>> {
match self.ids.get(index) {
Some((_chat_id, msg_id)) => Ok(*msg_id),
None => bail!("Chatlist index out of range"),
@@ -323,18 +323,19 @@ impl Chatlist {
/// - dc_lot_t::timestamp: the timestamp of the message. 0 if not applicable.
/// - dc_lot_t::state: The state of the message as one of the DC_STATE_* constants (see #dc_msg_get_state()).
// 0 if not applicable.
pub async fn get_summary(&self, context: &Context, index: usize, chat: Option<&Chat>) -> Lot {
pub async fn get_summary(
&self,
context: &Context,
index: usize,
chat: Option<&Chat>,
) -> Result<Lot> {
// The summary is created by the chat, not by the last message.
// This is because we may want to display drafts here or stuff as
// "is typing".
// Also, sth. as "No messages" would not work if the summary comes from a message.
let (chat_id, lastmsg_id) = match self.ids.get(index) {
Some(ids) => ids,
None => {
let mut ret = Lot::new();
ret.text2 = Some("ErrBadChatlistIndex".to_string());
return Lot::new();
}
None => bail!("Chatlist index out of range"),
};
Chatlist::get_summary2(context, *chat_id, *lastmsg_id, chat).await
@@ -343,50 +344,50 @@ impl Chatlist {
pub async fn get_summary2(
context: &Context,
chat_id: ChatId,
lastmsg_id: MsgId,
lastmsg_id: Option<MsgId>,
chat: Option<&Chat>,
) -> Lot {
) -> Result<Lot> {
let mut ret = Lot::new();
let chat_loaded: Chat;
let chat = if let Some(chat) = chat {
chat
} else if let Ok(chat) = Chat::load_from_db(context, chat_id).await {
} else {
let chat = Chat::load_from_db(context, chat_id).await?;
chat_loaded = chat;
&chat_loaded
} else {
return ret;
};
let (lastmsg, lastcontact) =
if let Ok(lastmsg) = Message::load_from_db(context, lastmsg_id).await {
if lastmsg.from_id == DC_CONTACT_ID_SELF {
(Some(lastmsg), None)
} else {
match chat.typ {
Chattype::Group | Chattype::Mailinglist => {
let lastcontact =
Contact::load_from_db(context, lastmsg.from_id).await.ok();
(Some(lastmsg), lastcontact)
}
Chattype::Single | Chattype::Undefined => (Some(lastmsg), None),
}
}
let (lastmsg, lastcontact) = if let Some(lastmsg_id) = lastmsg_id {
let lastmsg = Message::load_from_db(context, lastmsg_id).await?;
if lastmsg.from_id == DC_CONTACT_ID_SELF {
(Some(lastmsg), None)
} else {
(None, None)
};
match chat.typ {
Chattype::Group | Chattype::Mailinglist => {
let lastcontact =
Contact::load_from_db(context, lastmsg.from_id).await.ok();
(Some(lastmsg), lastcontact)
}
Chattype::Single | Chattype::Undefined => (Some(lastmsg), None),
}
}
} else {
(None, None)
};
if chat.id.is_archived_link() {
ret.text2 = None;
} else if lastmsg.is_none() || lastmsg.as_ref().unwrap().from_id == DC_CONTACT_ID_UNDEFINED
} else if let Some(mut lastmsg) =
lastmsg.filter(|msg| msg.from_id != DC_CONTACT_ID_UNDEFINED)
{
ret.text2 = Some(stock_str::no_messages(context).await);
} else {
ret.fill(&mut lastmsg.unwrap(), chat, lastcontact.as_ref(), context)
ret.fill(&mut lastmsg, chat, lastcontact.as_ref(), context)
.await;
} else {
ret.text2 = Some(stock_str::no_messages(context).await);
}
ret
Ok(ret)
}
pub fn get_index_for_id(&self, id: ChatId) -> Option<usize> {
@@ -684,7 +685,7 @@ mod tests {
chat_id1.set_draft(&t, Some(&mut msg)).await.unwrap();
let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap();
let summary = chats.get_summary(&t, 0, None).await;
let summary = chats.get_summary(&t, 0, None).await.unwrap();
assert_eq!(summary.get_text2().unwrap(), "foo: bar test"); // the linebreak should be removed from summary
}
}

View File

@@ -2295,7 +2295,7 @@ mod tests {
let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 1);
assert!(chats.get_chat_id(0).is_deaddrop());
let chat_id = chat::create_by_msg_id(&t, chats.get_msg_id(0).unwrap())
let chat_id = chat::create_by_msg_id(&t, chats.get_msg_id(0).unwrap().unwrap())
.await
.unwrap();
assert!(!chat_id.is_special());
@@ -2330,7 +2330,7 @@ mod tests {
.unwrap();
let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 2);
let chat_id = chat::create_by_msg_id(&t, chats.get_msg_id(0).unwrap())
let chat_id = chat::create_by_msg_id(&t, chats.get_msg_id(0).unwrap().unwrap())
.await
.unwrap();
let chat = chat::Chat::load_from_db(&t, chat_id).await.unwrap();
@@ -2351,7 +2351,7 @@ mod tests {
let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 1);
assert!(chats.get_chat_id(0).is_deaddrop());
let chat_id = chat::create_by_msg_id(&t, chats.get_msg_id(0).unwrap())
let chat_id = chat::create_by_msg_id(&t, chats.get_msg_id(0).unwrap().unwrap())
.await
.unwrap();
let chat = chat::Chat::load_from_db(&t, chat_id).await.unwrap();
@@ -2600,7 +2600,7 @@ mod tests {
assert_eq!(contact.get_display_name(), "h2");
let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap();
let msg = Message::load_from_db(&t, chats.get_msg_id(0).unwrap())
let msg = Message::load_from_db(&t, chats.get_msg_id(0).unwrap().unwrap())
.await
.unwrap();
assert_eq!(msg.is_dc_message, MessengerMessage::Yes);
@@ -2751,7 +2751,7 @@ mod tests {
.unwrap();
let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap();
let msg_id = chats.get_msg_id(0).unwrap();
let msg_id = chats.get_msg_id(0).unwrap().unwrap();
// Check that the ndn would be downloaded:
let headers = mailparse::parse_mail(raw_ndn).unwrap().headers;
@@ -2801,7 +2801,7 @@ mod tests {
.unwrap();
let chats = Chatlist::try_load(&t, 0, None, None).await.unwrap();
let msg_id = chats.get_msg_id(0).unwrap();
let msg_id = chats.get_msg_id(0).unwrap().unwrap();
let raw = include_bytes!("../test-data/message/gmail_ndn_group.eml");
dc_receive_imf(&t, raw, "INBOX", 1, false).await.unwrap();
@@ -2834,7 +2834,7 @@ mod tests {
.await
.unwrap();
let chats = Chatlist::try_load(context, 0, None, None).await.unwrap();
let msg_id = chats.get_msg_id(0).unwrap();
let msg_id = chats.get_msg_id(0).unwrap().unwrap();
Message::load_from_db(context, msg_id).await.unwrap()
}
@@ -2884,7 +2884,7 @@ mod tests {
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
assert_eq!(chats.len(), 1);
let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap())
let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap().unwrap())
.await
.unwrap();
let chat = chat::Chat::load_from_db(&t.ctx, chat_id).await.unwrap();
@@ -2957,7 +2957,7 @@ mod tests {
.await
.unwrap();
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap())
let chat_id = chat::create_by_msg_id(&t.ctx, chats.get_msg_id(0).unwrap().unwrap())
.await
.unwrap();
let chat = Chat::load_from_db(&t.ctx, chat_id).await.unwrap();

View File

@@ -1806,7 +1806,7 @@ mod tests {
let chats = Chatlist::try_load(context, 0, None, None).await.unwrap();
let chat_id = chat::create_by_msg_id(context, chats.get_msg_id(0).unwrap())
let chat_id = chat::create_by_msg_id(context, chats.get_msg_id(0).unwrap().unwrap())
.await
.unwrap();

View File

@@ -2834,7 +2834,7 @@ On 2020-10-25, Bob wrote:
.unwrap();
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
let msg_id = chats.get_msg_id(0).unwrap();
let msg_id = chats.get_msg_id(0).unwrap().unwrap();
let msg = Message::load_from_db(&t.ctx, msg_id).await.unwrap();
assert_eq!(

View File

@@ -331,7 +331,7 @@ impl TestContext {
// The chatlist describes what you see when you open DC, a list of chats and in each of them
// the first words of the last message. To get the last message overall, we look at the chat at the top of the
// list, which has the index 0.
let msg_id = chats.get_msg_id(0).unwrap();
let msg_id = chats.get_msg_id(0).unwrap().unwrap();
Message::load_from_db(&self.ctx, msg_id)
.await
.expect("failed to load msg")