Skip to content
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

impls for null-terminated FFI string types #801

Merged
merged 8 commits into from Mar 5, 2017

Conversation

jonhoo
Copy link
Contributor

@jonhoo jonhoo commented Mar 3, 2017

From #800: serde currently ships with an impl of Serialize and Deserialize for str and String, but not for the null-terminated C-like string types ffi::CStr and ffi::CString. Under the hood, these string implementations are very similar, and providing serialization implementations for the latter two shouldn't be too hard.

This patch adds serialization and deserialization of those types through null-terminated [u8]s. I'm guessing I should also implement tests for this, but didn't find where those should go. Feedback welcome!

@@ -295,6 +297,33 @@ impl Deserialize for String {

///////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "std")]
impl Deserialize for Box<CStr> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this impl unless you can implement it safely. The internal representation of CStr is not stable and there are plans to change it in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that's unfortunate. This is basically a direct translation of String::into_boxed_str, since the equivalent CString::into_boxed_cstr method does not exist. I think it's more common (and useful) to have the impl for CStr... Also allows working with, say Arc<CStr> (or arccstr). Should I then also remove the Serialize impl?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, keep the Serialize impl. It's fine to support serializing a type without supporting deserializing it.

fn deserialize<D>(deserializer: D) -> Result<CString, D::Error>
where D: Deserializer
{
let mut v: Vec<u8> = try!(Deserialize::deserialize(deserializer));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An empty vec would be an error right?

fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
(self.to_bytes_with_nul()).serialize(serializer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not require parentheses around self.to_bytes_with_nul().

@dtolnay
Copy link
Member

dtolnay commented Mar 3, 2017

What are the reasons for including the null terminator in the serialized representation?

fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
(self.to_bytes_with_nul()).serialize(serializer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using serialize_bytes would allow most serializers to serialize this more efficiently than other types of slices.

@jonhoo
Copy link
Contributor Author

jonhoo commented Mar 3, 2017

Good point about including the NULL bytes in the serialization. I'll remove that.

@dtolnay
Copy link
Member

dtolnay commented Mar 3, 2017

Tests for serialization should go here, tests for deserialization should go here, and tests for various deserialization error cases should go here.

@jonhoo
Copy link
Contributor Author

jonhoo commented Mar 3, 2017

Ah, so in writing the tests I realized that using serialize_bytes means we also need a way of turning the decoded Box<[u8]> into Vec<u8>. Unfortunately, there is no inverse function of Vec::into_boxed_slice, so there isn't an obvious way of doing that without doing an extra copy :/

@jonhoo
Copy link
Contributor Author

jonhoo commented Mar 3, 2017

Unless there's a way to deserialize_bytes into Vec<u8> instead of a Box<[u8]>.

@dtolnay
Copy link
Member

dtolnay commented Mar 3, 2017

ByteBuf implements Deserialize and Into<Vec<u8>>. Would that help? Something like:

let v: Vec<u8> = try!(ByteBuf::deserialize(deserializer)).into();

@jonhoo
Copy link
Contributor Author

jonhoo commented Mar 3, 2017

That works, though I'd have to import ByteBuf into de/impl.rs?

@dtolnay
Copy link
Member

dtolnay commented Mar 3, 2017

Yep that's fine.

@jonhoo
Copy link
Contributor Author

jonhoo commented Mar 4, 2017

So, it looks like we can also land deserialization for CStr once into_boxed_c_str lands (it is currently nightly-only). May be worth doing that in a separate PR though.

@jonhoo
Copy link
Contributor Author

jonhoo commented Mar 4, 2017

@dtolnay hmm -- why is bytes::ByteBuf only available on beta?

@dtolnay
Copy link
Member

dtolnay commented Mar 4, 2017

You're missing #[cfg(feature = "std")] on the import.

@jonhoo
Copy link
Contributor Author

jonhoo commented Mar 4, 2017

Okay, I think this is ready to merge @dtolnay. Deserialize for CStr can come later when into_boxed_c_str stabilizes.

@dtolnay dtolnay merged commit 2f988aa into serde-rs:master Mar 5, 2017
@clarfonthey
Copy link
Contributor

@jonhoo @dtolnay is there something open on serde's end to implement that once the method is stabilised? there's now a tracking issue for that feature at rust-lang/rust#40380

@jonhoo
Copy link
Contributor Author

jonhoo commented Mar 9, 2017

@clarcharr Not as far as I know, but I'm watching the issue and the PR, so will submit a follow-up PR here once it lands.

@dtolnay
Copy link
Member

dtolnay commented Mar 9, 2017

Thanks @clarcharr and @jonhoo, I filed #810 to track this on our end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants