Convert from a fixed-sized c_char array to CString - rust

My FFI binding returns a struct with fixed-size c_char arrays, and I would like to turn those into std::ffi::CString or std::String.
It looks like the CString::new function coerces the pointer to a vector.
use std::ffi::CString;
use std::os::raw::c_char;
#[repr(C)]
pub struct FFIStruct {
pub Id: [::std::os::raw::c_char; 256usize],
pub Description: [::std::os::raw::c_char; 256usize],
}
fn get_struct() -> Option<FFIStruct> {
println!("cheating");
None
}
pub fn main() {
match get_struct() {
Some(thing) =>
println!("Got id:{}",CString::new(thing.Id.as_ptr())),
None => (),
}
}
Here is the Rust Playground link.

C strings that you don't own should be translated using CStr, not CString. You can then convert it into an owned representation (CString) or convert it into a String:
extern crate libc;
use libc::c_char;
use std::ffi::CStr;
pub fn main() {
let id = [0 as c_char; 256];
let rust_id = unsafe { CStr::from_ptr(id.as_ptr()) };
let rust_id = rust_id.to_owned();
println!("{:?}", rust_id);
}
You should also use the libc crate for types like c_char.

There is also this kind of solution:
fn zascii(slice: &[c_char]) -> String {
String::from_iter(slice.iter().take_while(|c| **c != 0).map(|c| *c as u8 as char))
}

you can create std::ffi::CStr from a pointer but you have to use unsafe keyword.Like this
use std::ffi::CStr;
//use std::os::raw::c_char;
#[repr(C)]
pub struct FFIStruct {
pub id: [::std::os::raw::c_char; 256usize],
pub description: [::std::os::raw::c_char; 256usize],
}
fn get_struct() -> Option<FFIStruct> {
println!("cheating");
None
}
pub fn main() {
match get_struct() {
Some(thing) =>
println!("Got id:{:?}",unsafe{CStr::from_ptr(thing.id.as_ptr())}),
None => (),
}
}
you can also convert CStr into String by using this method
CStr::from_ptr(thing.id.as_ptr()).to_string_lossy()

Related

How to convert the name of a enum's variant to a String in RUST?

I am wondering how to implement a method for any enum that will return the variant identifier as a String or &'static str, without using any external crate. Something like:
pub enum MyEnum {
EnumVariant1
EnumVariant2
}
impl MyEnum {
fn to_string(&self) -> String {
// do Rust stuff here
}
}
As stated in my comment I believe a custom derive macro may be the easiest option (although I could be missing something) so here is a basic implementation of one:
// lib.rs in enum_name
extern crate self as enum_name;
pub use enum_name_derive::EnumName;
pub trait EnumName {
fn enum_name(&self) -> &'static str;
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(EnumName)]
#[allow(dead_code)]
enum MyEnum<'a, T> {
VariantA,
VariantB(T, i32),
AnotherOne { x: &'a str },
}
#[test]
fn test_enum_name() {
assert_eq!("VariantA", MyEnum::VariantA::<u32>.enum_name());
assert_eq!("VariantB", MyEnum::VariantB(1, 2).enum_name());
assert_eq!(
"AnotherOne",
MyEnum::AnotherOne::<u8> { x: "test" }.enum_name()
);
}
}
// lib.rs in enum_name_derive
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Fields};
#[proc_macro_derive(EnumName)]
pub fn derive_proto_read(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let ident = input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let variants = match input.data {
Data::Enum(data) => data.variants.into_iter().map(|variant| {
let ident = variant.ident;
let ident_string = ident.to_string();
let fields = match variant.fields {
Fields::Named(_) => quote!({ .. }),
Fields::Unnamed(_) => quote!((..)),
Fields::Unit => quote!(),
};
quote! {
Self::#ident#fields => #ident_string
}
}),
_ => panic!("not an enum"),
};
(quote! {
impl #impl_generics enum_name::EnumName for #ident #ty_generics #where_clause {
fn enum_name(&self) -> &'static str {
match self {
#(#variants),*
}
}
}
})
.into()
}

Rust: Using two u8 struct fields as a u16

For a Gameboy emulator, you have two u8 fields for registers A and F, but they can sometimes be accessed as AF, a combined u16 register.
In C, it looks like you can do something like this:
struct {
union {
struct {
unsigned char f;
unsigned char a;
};
unsigned short af;
};
};
(Taken from here)
Is there a way in Rust, ideally without unsafe, of being able to access two u8s as registers.a/registers.f, but also be able to use them as the u16 registers.af?
I can give you a couple of ways to do it. First is a straightforward unsafe analogue but without boilerplate, the second one is safe but explicit.
Unions in rust are very similar, so you can translate it to this:
#[repr(C)]
struct Inner {
f: u8,
a: u8,
}
#[repr(C)]
union S {
inner: Inner,
af: u16,
}
// Usage:
// Putting data is safe:
let s = S { af: 12345 };
// but retrieving is not:
let a = unsafe { s.inner.a };
Or as an alternative you may manually do all of the explicit casts wrapped in a structure:
#[repr(transparent)]
// This is optional actually but allows a chaining,
// you may remove these derives and change method
// signatures to `&self` and `&mut self`.
#[derive(Clone, Copy)]
struct T(u16);
impl T {
pub fn from_af(af: u16) -> Self {
Self(af)
}
pub fn from_a_f(a: u8, f: u8) -> Self {
Self::from_af(u16::from_le_bytes([a, f]))
}
pub fn af(self) -> u16 {
self.0
}
pub fn f(self) -> u8 {
self.0.to_le_bytes()[0]
}
pub fn set_f(self, f: u8) -> Self {
Self::from_a_f(self.a(), f)
}
pub fn a(self) -> u8 {
self.0.to_le_bytes()[1]
}
pub fn set_a(self, a: u8) -> Self {
Self::from_a_f(a, self.f())
}
}
// Usage:
let t = T::from_af(12345);
let a = t.a();
let new_af = t.set_a(12).set_f(t.f() + 1).af();

Convert enum variants with named data into separate structs using procedural macros

I'm writing a procedural macro to convert the variants of an enum into individual structs and implement some traits for that struct.
This works fine for unit and unnamed variants, but variants with named data will cause it to silently fail :).
Here is an example proc_macro definition:
extern crate proc_macro;
use quote::ToTokens;
use proc_macro::TokenStream;
use quote::quote;
use syn::{Data, DataEnum, DeriveInput};
#[proc_macro_derive(MyProcMacro)]
pub fn derive_my_proc_macro(input: TokenStream) -> TokenStream {
let ast: DeriveInput = syn::parse(input).unwrap();
// Error out if we're not annotating an enum
let data: DataEnum = match ast.data {
Data::Enum(d) => d,
_ => panic!("My structs can only be derived for enums"),
};
let variants = data.variants.iter();
let variant_structs = variants.map(|v| {
let var_id = &v.ident;
let fields = v.fields.clone().into_token_stream();
quote! {
pub struct #var_id #fields;
/* Implement traits for the new struct and stuff */
}
});
let gen = quote! {
#(#variant_structs)*
};
gen.into()
}
When I run it on this code:
#[derive(MyProcMacro)]
enum AllTypesOfVariants {
Unit,
OneUnNamed(bool),
MultiUnNamed(bool, bool, bool),
Named { _thing: bool },
MultiNamed { _thing: bool, _thing2: bool },
}
I get this expanded code (via cargo expand):
pub struct Unit;
pub struct OneUnNamed(bool);
pub struct MultiUnNamed(bool, bool, bool);
pub struct Named {
_thing: bool,
}
The expected result however would be:
pub struct Unit;
pub struct OneUnNamed(bool);
pub struct MultiUnNamed(bool, bool, bool);
pub struct Named {
_thing: bool,
}
pub struct MultiNamed {
_thing: bool,
_thing2: bool
}
The problem is in the semi-colon in the quote!().
Structs with unnamed fields should be terminated with a semicolon:
pub struct MultiUnNamed(bool, bool, bool);
But structs with named fields shouldn't:
pub struct MultiNamed {
_thing: bool,
_thing2: bool
}
The problem was solved by replacing:
quote! {
pub struct #var_id #fields;
}
with
match &v.fields {
Fields::Named(_) => {
quote! {
pub struct #var_id #fields
}
},
_ => {
quote! {
pub struct #var_id #fields;
}
}
}
(Also had to import syn::Fields)

Deserialize a JSON string or array of strings into a Vec

I'm writing a crate that interfaces with a JSON web API. One endpoint usually returns responses of the form { "key": ["value1", "value2"] }, but sometimes there's only one value for the key, and the endpoint returns { "key": "value" } instead of { "key": ["value"] }
I wanted to write something generic for this that I could use with #[serde(deserialize_with)] like so:
#[derive(Deserialize)]
struct SomeStruct {
#[serde(deserialize_with = "deserialize_string_or_seq_string")]
field1: Vec<SomeStringNewType>,
#[serde(deserialize_with = "deserialize_string_or_seq_string")]
field2: Vec<SomeTypeWithCustomDeserializeFromStr>,
}
#[derive(Deserialize)]
struct SomeStringNewType(String);
struct SomeTypeWithCustomDeserializeFromStr(String);
impl ::serde::de::Deserialize for SomeTypeWithCustomDeserializeFromStr {
// Some custom implementation here
}
How can I write a deserialize_string_or_seq_string to be able to do this?
In case you want to deserialize a single string or a list of strings into the more general Vec<String> instead of a custom type, the following is a simpler solution for Serde 1.0:
extern crate serde;
#[macro_use] extern crate serde_derive;
extern crate serde_json;
use std::fmt;
use std::marker::PhantomData;
use serde::de;
use serde::de::{Deserialize, Deserializer};
#[derive(Deserialize, Debug, Clone)]
pub struct Parent {
#[serde(deserialize_with = "string_or_seq_string")]
pub strings: Vec<String>,
}
fn main() {
let list_of_strings: Parent = serde_json::from_str(r#"{ "strings": ["value1", "value2"] }"#).unwrap();
println!("list of strings: {:?}", list_of_strings);
// Prints:
// list of strings: Parent { strings: ["value1", "value2"] }
let single_string: Parent = serde_json::from_str(r#"{ "strings": "value" }"#).unwrap();
println!("single string: {:?}", single_string);
// Prints:
// single string: Parent { strings: ["value"] }
}
fn string_or_seq_string<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
where D: Deserializer<'de>
{
struct StringOrVec(PhantomData<Vec<String>>);
impl<'de> de::Visitor<'de> for StringOrVec {
type Value = Vec<String>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string or list of strings")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where E: de::Error
{
Ok(vec![value.to_owned()])
}
fn visit_seq<S>(self, visitor: S) -> Result<Self::Value, S::Error>
where S: de::SeqAccess<'de>
{
Deserialize::deserialize(de::value::SeqAccessDeserializer::new(visitor))
}
}
deserializer.deserialize_any(StringOrVec(PhantomData))
}
This solution also works under the 0.9 release of Serde with the following changes:
remove the lifetimes
SeqAccess -> SeqVisitor
SeqAccessDeserializer -> SeqVisitorDeserializer
MapAccess -> MapVisitor
MapAccessDeserializer -> MapVisitorDeserializer
This solution works for Serde 1.0.
The way I found also required me to write a custom deserializer, because I needed one that would call visitor.visit_newtype_struct to try deserializing newtypes, and there don't seem to be any in-built into serde that do so. (I was expecting something like the ValueDeserializer series of types.)
A self-contained example is below. The SomeStruct is deserialized correctly for both inputs, one where the values are JSON arrays of strings, and the other where they're just strings.
#[macro_use]
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
fn main() {
#[derive(Debug, Deserialize)]
struct SomeStringNewType(String);
#[derive(Debug)]
struct SomeTypeWithCustomDeserializeFromStr(String);
impl<'de> ::serde::Deserialize<'de> for SomeTypeWithCustomDeserializeFromStr {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: ::serde::Deserializer<'de> {
struct Visitor;
impl<'de> ::serde::de::Visitor<'de> for Visitor {
type Value = SomeTypeWithCustomDeserializeFromStr;
fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "a string")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: ::serde::de::Error {
Ok(SomeTypeWithCustomDeserializeFromStr(v.to_string() + " custom"))
}
}
deserializer.deserialize_any(Visitor)
}
}
#[derive(Debug, Deserialize)]
struct SomeStruct {
#[serde(deserialize_with = "deserialize_string_or_seq_string")]
field1: Vec<SomeStringNewType>,
#[serde(deserialize_with = "deserialize_string_or_seq_string")]
field2: Vec<SomeTypeWithCustomDeserializeFromStr>,
}
let x: SomeStruct = ::serde_json::from_str(r#"{ "field1": ["a"], "field2": ["b"] }"#).unwrap();
println!("{:?}", x);
assert_eq!(x.field1[0].0, "a");
assert_eq!(x.field2[0].0, "b custom");
let x: SomeStruct = ::serde_json::from_str(r#"{ "field1": "c", "field2": "d" }"#).unwrap();
println!("{:?}", x);
assert_eq!(x.field1[0].0, "c");
assert_eq!(x.field2[0].0, "d custom");
}
/// Deserializes a string or a sequence of strings into a vector of the target type.
pub fn deserialize_string_or_seq_string<'de, T, D>(deserializer: D) -> Result<Vec<T>, D::Error>
where T: ::serde::Deserialize<'de>, D: ::serde::Deserializer<'de> {
struct Visitor<T>(::std::marker::PhantomData<T>);
impl<'de, T> ::serde::de::Visitor<'de> for Visitor<T>
where T: ::serde::Deserialize<'de> {
type Value = Vec<T>;
fn expecting(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "a string or sequence of strings")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where E: ::serde::de::Error {
let value = {
// Try parsing as a newtype
let deserializer = StringNewTypeStructDeserializer(v, ::std::marker::PhantomData);
::serde::Deserialize::deserialize(deserializer)
}.or_else(|_: E| {
// Try parsing as a str
let deserializer = ::serde::de::IntoDeserializer::into_deserializer(v);
::serde::Deserialize::deserialize(deserializer)
})?;
Ok(vec![value])
}
fn visit_seq<A>(self, visitor: A) -> Result<Self::Value, A::Error>
where A: ::serde::de::SeqAccess<'de> {
::serde::Deserialize::deserialize(::serde::de::value::SeqAccessDeserializer::new(visitor))
}
}
deserializer.deserialize_any(Visitor(::std::marker::PhantomData))
}
// Tries to deserialize the given string as a newtype
struct StringNewTypeStructDeserializer<'a, E>(&'a str, ::std::marker::PhantomData<E>);
impl<'de, 'a, E> ::serde::Deserializer<'de> for StringNewTypeStructDeserializer<'a, E> where E: ::serde::de::Error {
type Error = E;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: ::serde::de::Visitor<'de> {
visitor.visit_newtype_struct(self)
}
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: ::serde::de::Visitor<'de> {
// Called by newtype visitor
visitor.visit_str(self.0)
}
forward_to_deserialize_any! {
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str bytes
byte_buf option unit unit_struct newtype_struct seq tuple tuple_struct map
struct enum identifier ignored_any
}
}
I found this pattern to work for me in a similar situation:
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
enum ParameterValue {
Primitive(String),
List(Vec<String>),
}
#[derive(Debug, Serialize, Deserialize)]
struct Parameter {
name: String,
value: ParameterValue,
}
example primitive:
let primitive = Parameter {
name: String::from("theKey"),
value: ParameterValue::Primitive(String::from("theValue")),
};
let primitive_serialized = serde_json::to_string(&primitive).unwrap();
println!("{primitive_serialized}");
let primitive_again: Parameter = serde_json::from_str(&primitive_serialized).unwrap();
println!("{primitive_again:?}");
Prints:
{"name":"theKey","value":"theValue"}
Parameter { name: "theKey", value: Primitive("theValue") }
example array:
let list = Parameter {
name: String::from("theKey"),
value: ParameterValue::List(vec![String::from("v1"), String::from("v2")]),
};
let list_serialized = serde_json::to_string(&list).unwrap();
println!("{list_serialized}");
let list_again: Parameter = serde_json::from_str(&list_serialized).unwrap();
println!("{list_again:?}");
Prints:
{"name":"theKey","value":["v1","v2"]}
Parameter { name: "theKey", value: List(["v1", "v2"]) }

Is it possible to create a macro to implement builder pattern methods?

I have a builder pattern implemented for my struct:
pub struct Struct {
pub grand_finals_modifier: bool,
}
impl Struct {
pub fn new() -> Struct {
Struct {
grand_finals_modifier: false,
}
}
pub fn grand_finals_modifier<'a>(&'a mut self, name: bool) -> &'a mut Struct {
self.grand_finals_modifier = grand_finals_modifier;
self
}
}
Is it possible in Rust to make a macro for methods like this to generalize and avoid a lot of duplicating code? Something that we can use as the following:
impl Struct {
builder_field!(hello, bool);
}
After reading the documentation, I've come up with this code:
macro_rules! builder_field {
($field:ident, $field_type:ty) => {
pub fn $field<'a>(&'a mut self,
$field: $field_type) -> &'a mut Self {
self.$field = $field;
self
}
};
}
struct Struct {
pub hello: bool,
}
impl Struct {
builder_field!(hello, bool);
}
fn main() {
let mut s = Struct {
hello: false,
};
s.hello(true);
println!("Struct hello is: {}", s.hello);
}
It does exactly what I need: creates a public builder method with specified name, specified member and type.
To complement the already accepted answer, since it is 4 years old by now, you should check out the crate rust-derive-builder. It uses procedural macros to automatically implement the builder pattern for any struct.

Resources