Description
Proposal
Problem statement
In multi-language projects that need to perform interop with C or C++, you will often need to manipulate most of your strings using the core::ffi::CStr
type rather than the usual str
type, because you need the string to be nul-terminated before you can pass it into the C/C++ codebase. This means that working with nul-terminated strings should be somewhat convenient.
Unfortunately, it's currently very difficult to print a nul-terminated string. The type does not implement Display
and there's no display()
function either. Currently, you have to do something like this to print it:
println!("{}", my_string.to_string_lossy());
Or use an extension trait for CStr
.
What about Debug
?
It doesn't print the right thing.
println!("{:?}", c"Hello, here is a string: \n\"\'\xff.");
"Hello, here is a string: \n\"\'\xff."
It wraps the string in quotes, and also escapes various characters such as quotes and newlines.
Motivating examples or use cases
This is motivated by the Linux Kernel, where we currently have a custom CStr
type that implements Display
. We would like to move away from the custom CStr
so that we can use c""
literals. However, there are many places where we print a nul-terminated string for various reasons.
dev_debug!("Registered {name}.");
This becomes:
use kernel::prelude::*; // for CStrExt
dev_debug!("Registered {}.", name.display());
Ideally we would like to be able to continue printing strings with the original syntax.
We don't really care about utf-8 here, and the thing we are printing to doesn't either. Printing replacement characters like how String::from_utf8_lossy
would be fine.
Solution sketch
The solution sketch is to implement Display
for CStr
and CString
. The implementation would be the same as for the ByteStr
type.
Alternatives
The primary question to consider here is how to deal with bytes that are not valid utf-8.
Add a .display()
function
The Path
type has a similar problem, but the standard library has chosen to handle it by adding a .display()
method. The Path
type does not implement the Display
trait directly.
I think that we should not repeat this solution for CStr
. The Path
type carries with it the intent that you are being careful with your paths and that you want to avoid accidentally breaking a path by round-tripping it through the String
type. The CStr
type does not carry the same intent with it, and implementing Display
is more convenient because it lets you print with the "{name}"
syntax instead of having to do "{}", name.display()
.
How to escape the string
This proposal says that the default way to print a CStr
should be to use replacement characters rather than some other form of escaping. This is because cstr printing is generally used to display the string to a user, and � is much better at conveying that the data is invalid than \xff
to a non-technical user.
Links and related work
Zulip thread: zulip
Adding OsStr::display
: tracking issue
LKML thread: lkml
What happens now?
This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.
Possible responses
The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):
- We think this problem seems worth solving, and the standard library might be the right place to solve it.
- We think that this probably doesn't belong in the standard library.
Second, if there's a concrete solution:
- We think this specific solution looks roughly right, approved, you or someone else should implement this. (Further review will still happen on the subsequent implementation PR.)
- We're not sure this is the right solution, and the alternatives or other materials don't give us enough information to be sure about that. Here are some questions we have that aren't answered, or rough ideas about alternatives we'd want to see discussed.