-
-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
change type of dc_msg_t.text to String #283
Conversation
src/dc_chat.rs
Outdated
@@ -1001,7 +991,7 @@ unsafe fn set_draft_raw(context: &Context, chat_id: uint32_t, msg: *mut dc_msg_t | |||
// save new draft | |||
if !msg.is_null() { | |||
if (*msg).type_0 == Viewtype::Text { | |||
if (*msg).text.is_null() || *(*msg).text.offset(0isize) as libc::c_int == 0i32 { | |||
if (*msg).text.is_none() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You change the logic here. Existing code checks for
(*msg).text.is_none() || (*msg).text.unwrap().is_empty()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@KAction If I remember correctly you added the check for empty string but removed it now?
src/dc_msg.rs
Outdated
@@ -827,13 +834,21 @@ pub unsafe fn dc_msg_get_summarytext( | |||
return dc_strdup(0 as *const libc::c_char); | |||
} | |||
|
|||
dc_msg_get_summarytext_by_raw( | |||
let msgtext_ptr = if let Some(ref text) = (*msg).text { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use map_or here.
src/dc_msg.rs
Outdated
@@ -1049,8 +1064,7 @@ pub unsafe fn dc_msg_set_text(mut msg: *mut dc_msg_t, text: *const libc::c_char) | |||
if msg.is_null() || (*msg).magic != 0x11561156i32 as libc::c_uint { | |||
return; | |||
} | |||
free((*msg).text as *mut libc::c_void); | |||
(*msg).text = dc_strdup(text); | |||
(*msg).text = if text.is_null() { None } else { Some(to_string(text)) }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
map_or
6dcc8d8
to
35c2daa
Compare
src/dc_chat.rs
Outdated
if (*msg).text.is_null() || *(*msg).text.offset(0isize) as libc::c_int == 0i32 { | ||
OK_TO_CONTINUE = false; | ||
OK_TO_CONTINUE = match (*msg).text { | ||
None => false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe use .map_or
here as well?
I am ok with merging as-is after All those |
Okay. Plus-control passed. Master builds fine. |
@link2xt No. Somewhy it breaks tests. Investigating. |
2054cd0
to
fb1622a
Compare
I think it is ready. The catch was that |
src/dc_chat.rs
Outdated
if OK_TO_CONTINUE { | ||
dbg!(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these dbg!
s going to be useful later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops. This is bug. Just fixed.
src/dc_chat.rs
Outdated
@@ -1001,7 +991,7 @@ unsafe fn set_draft_raw(context: &Context, chat_id: uint32_t, msg: *mut dc_msg_t | |||
// save new draft | |||
if !msg.is_null() { | |||
if (*msg).type_0 == Viewtype::Text { | |||
if (*msg).text.is_null() || *(*msg).text.offset(0isize) as libc::c_int == 0i32 { | |||
if (*msg).text.is_none() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@KAction If I remember correctly you added the check for empty string but removed it now?
Previous version of patch, that changed type of `dc_msg_t.text' to String had been breaking `prepare_and_send' test in Python. This commit adds same regression test, reimplemented in Rust, since running Rust tests is simplier and faster.
src/dc_chat.rs
Outdated
@@ -725,7 +725,7 @@ unsafe fn prepare_msg_raw( | |||
timestamp, | |||
(*msg).type_0, | |||
(*msg).state, | |||
if !(*msg).text.is_null() { Some(as_str((*msg).text)) } else { None }, | |||
(*msg).text.deref().unwrap_or(""), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dignifiedquire previously said that using unstable features is discouraged because the goal is to move to stable Rust. This seems to be the line that requires inner_deref
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay.
|
||
let res = dc_truncate_str(as_str((*msg).text), 30000); | ||
res.strdup() | ||
if let Some(ref text) = (*msg).text { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously, code panic!'ed if msg.text
is null. Now, this code returns NULL
. Probably this is right thing to do.
On other hand, I think that check for msg.is_null()
is wrong. Function should not silently fail on bogus input, it should panic, imho. I spent some time debugging, while dc_get_msg_id(NULL) == 0
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All those is_null
checks are from the legacy C code. It accepted nulls everywhere and proceeded as if nothing happened instead of failing. That is in spirit of C, where free
accepts NULL.
For Rust code, I am in favor of fail-fast design. Users of the library should avoid passing nulls where data is expected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quite off-topic, but I disagree that it is in spirit of C. free
is exception, not rule. Most C API cause UB (e.g SIGSEGV) on NULL pointer: fopen
, fprint
, open
, readdir
, regcomp
, ...
On rust code, good. Will add some asserts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will add some asserts.
Not in this PR, though. These changes need to be aligned with bindings/android/desktop/ios code, they may rely on this behavior.
07d7d54
to
9ab922a
Compare
Also, remove `send-garbage' command from REPL, since it is not possible to send non-utf8 string anymore.
} else { | ||
"" | ||
}, | ||
(*msg).text.as_ref().map(String::as_str).unwrap_or(""), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.unwrap_or_default()
would be the same? Not that I mind.
.text | ||
.as_ref() | ||
.map(|s| CString::yolo(String::as_str(s))); | ||
let msgtext_ptr = msgtext_c.map_or(ptr::null(), |s| s.as_ptr()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, this is nice! I think there are a lot of places that simply do s.as_ptr()
instead of the full .map_or(ptr::null(), |s| s.as_ptr())
and that's probably the cause of a bunch of crashes.
@@ -31,7 +32,7 @@ pub struct dc_msg_t<'a> { | |||
pub timestamp_sort: i64, | |||
pub timestamp_sent: i64, | |||
pub timestamp_rcvd: i64, | |||
pub text: *mut libc::c_char, | |||
pub text: Option<String>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd kind of argue that this should be just be String
and use ""
if there is nothing. I think the None
case is really an artefact of the C API and only needs to be replicated on that boundary layer. A lot of things probably become easier if you can just assume this is always a valid string instead of having to handle the Option.
I don't feel too strongly though, this PR is certainly already an improvement as is!
let contact = dc_create_contact( | ||
ctx, | ||
b"\x00".as_ptr().cast(), | ||
b"dest@example.com\x00".as_ptr().cast(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could also write this as "dest@example.com".strdup()
I think (and above "".strdup()
).
But TIL about .cast()
though, nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strdup
performs allocation, and must be free
d manually. I'd rather have Rust do it for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PS. Since there is goal to drop unstable feature, cast
will be gone eventually. Sad, I liked him.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@KAction cast
is stable now: rust-lang/rust#62713
Okay. What is missing for merging? |
@dignifiedquire has to change review to "approve" |
Let's assume @dignifiedquire is busy and merge anyway. Things can always be changed later. |
Also, remove `send-garbage' command from REPL, since it is not possible to send
non-utf8 string anymore.