I'm writing a Rust wrapper for a binary protocol (Netlink) and for that purpose I need to encode some data (Strings and different sorts of ints and uints) into some kind of buffer, and I saw that Vec<u8> is uausally used for that. My current pseudocode looks like this:
struct NetlinkHeader {
length: u32,
_type: u16,
flags: u16,
sequence: u32,
pid: u32
}
impl NetlinkSerializable for NetlinkHeader {
fn to_wire_format(&self) -> Result<str, &'static str> {
let mut binary_data: Vec<u8> = Vec::with_capacity(16);
binary_data.add_binary_representation(self.length);
binary_data.add_binary_representation(self._type);
binary_data.add_binary_representation(self.flags);
binary_data.add_binary_representation(self.sequence);
binary_data.add_binary_representation(self.pid);
}
}
I need help implementing something that does what add_binary_representation in the above pseudocode would do.
Related
Is it possible to define fmt::Display and fmt::Debug together, i.e. such that they use the same implementation?
Assume we have the below sample code (purely for demonstration purposes):
use std::fmt;
struct MyDate {
pub year: u16,
pub month: u8,
pub day: u8
}
impl PartialEq for MyDate {
fn eq(&self, other: &Self) -> bool {
self.year == other.year && self.month == other.month && self.day == other.day
}
}
impl fmt::Display for MyDate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}-{:02}-{:02}", self.year, self.month, self.day)
}
}
impl fmt::Debug for MyDate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
fn main() {
let d1 = MyDate { year: 2008, month: 9, day: 10 };
let d2 = MyDate { year: 2008, month: 9, day: 10 };
println!("Date = {}", d1); // requires fmt::Display
assert_eq!(d1, d2); // requires fmt::Debug
}
It seems that in order to print my class using println and write unit tests using assert_eq, I need to define both fmt traits. Is there a way to have 1 "print" implementation that simultaneously defines fmt::Display and fmt::Debug? For example something along the lines of impl fmt::Debug, fmt::Display for MyDate { ... } or similar?
Or is it common practice to just put #[derive(Debug)] in front of any class? Apologies if my question is naïve, as I am new to rust.
In most cases, Display and Debug have different output. When it makes sense to use the same formatting in both cases, the code you've written is fine. It would also be fine to #[derive(Debug)] — it's your decision to make. I think the important thing to keep in mind is that Debug should not leave anything out, and be unambiguous.
In the case you show, the Display format shows all of the struct's fields completely accurately, so it's perfectly fine to reuse Display to implement Debug. If you had a lot of types like this, you could use a simple macro to generate Debug implementations that forward to Display.
By the way, I would suggest using #[derive(PartialEq)] instead of the manual PartialEq implementation you show. It's completely equivalent, and avoids the dangerous failure mode of forgetting to compare a newly added field.
Serde supports applying custom attributes that are used with #[derive(Serialize)]:
#[derive(Serialize)]
struct Resource {
// Always serialized.
name: String,
// Never serialized.
#[serde(skip_serializing)]
hash: String,
// Use a method to decide whether the field should be skipped.
#[serde(skip_serializing_if = "Map::is_empty")]
metadata: Map<String, String>,
}
I understand how to implement a procedural macro (Serialize in this example) but what should I do to implement #[serde(skip_serializing)]? I was unable to find this information anywhere. The docs don't even mention this. I have tried to look at the serde-derive source code but it is very complicated for me.
First you must register all of your attributes in the same place you register your procedural macro. Let's say we want to add two attributes (we still don't talk what will they belong to: structs or fields or both of them):
#[proc_macro_derive(FiniteStateMachine, attributes(state_transitions, state_change))]
pub fn fxsm(input: TokenStream) -> TokenStream {
// ...
}
After that you may already compile your user code with the following:
#[derive(Copy, Clone, Debug, FiniteStateMachine)]
#[state_change(GameEvent, change_condition)] // optional
enum GameState {
#[state_transitions(NeedServer, Ready)]
Prepare { players: u8 },
#[state_transitions(Prepare, Ready)]
NeedServer,
#[state_transitions(Prepare)]
Ready,
}
Without that compiler will give a error with message like:
state_change does not belong to any known attribute.
These attributes are optional and all we have done is allow them to be to specified. When you derive your procedural macro you may check for everything you want (including attributes existence) and panic! on some condition with meaningful message which will be told by the compiler.
Now we will talk about handling the attribute! Let's forget about state_transitions attribute because it's handling will not vary too much from handling struct/enum attributes (actually it is only a little bit more code) and talk about state_change. The syn crate gives you all the needed information about definitions (but not implementations unfortunately (I am talking about impl here) but this is enough for handling attributes of course). To be more detailed, we need syn::DeriveInput, syn::Body, syn::Variant, syn::Attribute and finally syn::MetaItem.
To handle the attribute of a field you need to go through all these structures from one to another. When you reach Vec<syn:: Attribute> - this is what you want, a list of all attributes of a field. Here our state_transitions can be found. When you find it, you may want to get its content and this can be done by using matching syn::MetaItem enum. Just read the docs :) Here is a simple example code which panics when we find state_change attribute on some field plus it checks does our target entity derive Copy or Clone or neither of them:
#[proc_macro_derive(FiniteStateMachine, attributes(state_transitions, state_change))]
pub fn fxsm(input: TokenStream) -> TokenStream {
// Construct a string representation of the type definition
let s = input.to_string();
// Parse the string representation
let ast = syn::parse_derive_input(&s).unwrap();
// Build the impl
let gen = impl_fsm(&ast);
// Return the generated impl
gen.parse().unwrap()
}
fn impl_fsm(ast: &syn::DeriveInput) -> Tokens {
const STATE_CHANGE_ATTR_NAME: &'static str = "state_change";
if let syn::Body::Enum(ref variants) = ast.body {
// Looks for state_change attriute (our attribute)
if let Some(ref a) = ast.attrs.iter().find(|a| a.name() == STATE_CHANGE_ATTR_NAME) {
if let syn::MetaItem::List(_, ref nested) = a.value {
panic!("Found our attribute with contents: {:?}", nested);
}
}
// Looks for derive impls (not our attribute)
if let Some(ref a) = ast.attrs.iter().find(|a| a.name() == "derive") {
if let syn::MetaItem::List(_, ref nested) = a.value {
if derives(nested, "Copy") {
return gen_for_copyable(&ast.ident, &variants, &ast.generics);
} else if derives(nested, "Clone") {
return gen_for_clonable(&ast.ident, &variants, &ast.generics);
} else {
panic!("Unable to produce Finite State Machine code on a enum which does not drive Copy nor Clone traits.");
}
} else {
panic!("Unable to produce Finite State Machine code on a enum which does not drive Copy nor Clone traits.");
}
} else {
panic!("How have you been able to call me without derive!?!?");
}
} else {
panic!("Finite State Machine must be derived on a enum.");
}
}
fn derives(nested: &[syn::NestedMetaItem], trait_name: &str) -> bool {
nested.iter().find(|n| {
if let syn::NestedMetaItem::MetaItem(ref mt) = **n {
if let syn::MetaItem::Word(ref id) = *mt {
return id == trait_name;
}
return false
}
false
}).is_some()
}
You may be interested in reading serde_codegen_internals, serde_derive, serenity's #[command] attr, another small project of mine - unique-type-id, fxsm-derive. The last link is actually my own project to explain to myself how to use procedural macros in Rust.
After some Rust 1.15 and updating the syn crate, it is no longer possible to check derives of a enums/structs, however, everything else works okay.
You implement attributes on fields as part of the derive macro for the struct (you can only implement derive macros for structs and enums).
Serde does this by checking every field for an attribute within the structures provided by syn and changing the code generation accordingly.
You can find the relevant code here: https://github.com/serde-rs/serde/blob/master/serde_derive/src/internals/attr.rs
To expand Victor Polevoy's answer when it comes to the state_transitions attribute. I'm providing an example of how to extract the field attribute #[state_transitions(NeedServer, Ready)] on a enum that derives #[derive(FiniteStateMachine)]:
#[derive(FiniteStateMachine)]
enum GameState {
#[state_transitions(NeedServer, Ready)] // <-- extract this
Prepare { players: u8 },
#[state_transitions(Prepare, Ready)]
NeedServer,
#[state_transitions(Prepare)]
Ready,
}
use proc_macro::TokenStream;
#[proc_macro_derive(FiniteStateMachine, attributes(state_transitions))]
pub fn finite_state_machine(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();
// Extract the enum variants
let variants: Vec<&syn::Variant> = match &ast.data {
syn::Data::Enum(ref data_enum) => data_enum.variants.iter().collect(),
other => panic!("#[derive(FiniteStateMachine)] expects enum, got {:#?}", other)
};
// For each variant, extract the attributes
let _ = variants.iter().map(|variant| {
let attrs = variant.attrs.iter()
// checks attribute named "state_transitions(...)"
.find_map(|attr| match attr.path.is_ident("state_transitions") {
true => Some(&attr.tokens),
false => None,
})
.expect("#[derive(FiniteStateMachine)] expects attribute macros #[state_transitions(...)] on each variant, found none");
// outputs: attr: "(NeedServer, Ready)"
eprintln!("attr: {:#?}", attrs.to_string());
// do something with the extracted attributes
...
})
.collect();
...
}
The content of the extracted attrs (typed TokenStream) looks like this:
TokenStream [
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "NeedServer",
span: #0 bytes(5511..5521),
},
Punct {
ch: ',',
spacing: Alone,
span: #0 bytes(5521..5522),
},
Ident {
ident: "Ready",
span: #0 bytes(5523..5528),
},
],
span: #0 bytes(5510..5529),
},
]
I am trying to play with Rust's std::hash function:
use std::hash::{hash, Hash, SipHasher};
#[test]
fn hash_test() {
println!("{}", hash::<_, SipHasher>(&"hello"));
}
I get this error:
error: use of unstable library feature 'hash': module was recently redesigned
My Rust version is:
rustc 1.0.0-beta (9854143cb 2015-04-02) (built 2015-04-02)
Is this syntax no longer valid?
The original question was trying to use a feature that was unstable - which means it isn't allowed to be used in a stable release, like 1.0-beta or 1.0. Since them, the function has been removed from the language.
The replacement is to write your own version, which allows you to specify the hash function. Additionally, using SipHasher directly is deprecated. If you need a specific hashing algorithm, you should pull it from crates.io. Otherwise, you can use an unspecified hashing algorithm from the standard library:
use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;
#[derive(Hash)]
struct Person {
id: u32,
name: String,
phone: u64,
}
fn my_hash<T>(obj: T) -> u64
where
T: Hash,
{
let mut hasher = DefaultHasher::new();
obj.hash(&mut hasher);
hasher.finish()
}
fn main() {
let person1 = Person {
id: 5,
name: "Janet".to_string(),
phone: 555_666_7777,
};
let person2 = Person {
id: 5,
name: "Bob".to_string(),
phone: 555_666_7777,
};
println!("{}", my_hash(person1));
println!("{}", my_hash(person2));
}
Is there a way in Swift to define an extension for type Double to accept String as initializer? In a nutshell, just to figure out feasibility, I need this to work:
var double:Double = "one"
println(double) // Outputs "1.0"
I am guessing it should be made compliant to StringLiteralConvertible, but not sure about the details.
So, you want to natural-language-parse a string, and generate a floating-point number from it?
Well, the extension is the easy part. Just create a failable initializer for it:
let digits = [
"zero", "one", "two", "three",
"four", "five", "six", "seven",
"eight", "nine",
]
extension Double {
init?(fromEnglishString s: String) {
if let digit = find(digits, s) {
self.init(Double(digit))
}
else {
return nil
}
}
}
let d = Double(fromEnglishString: "one")
// d is {Some 1.0}
The hard part is going to be finding a good parser for all the ways you can express numbers in English (especially floating-point numbers). That's much more tricky. You might find this more language-agnostic answer interesting.
You could also write a StringLiteralConvertible extension for it. However, this is only for when you are initializing your value directly from a string literal at compile time – which would be a bit pointless, I mean, do you really need word-based number literals in your source code? The other problem is literal convertible initializers can't be failable, so you'll be stuck with returning a default value (maybe NaN?) if the string can't be parsed.
Nevertheless, if you really want one:
extension Double: StringLiteralConvertible {
public typealias StringLiteralType = String
public typealias UnicodeScalarLiteralType = String
public typealias ExtendedGraphemeClusterLiteralType = String
public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
self.init(stringLiteral: value)
}
public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
self.init(stringLiteral: value)
}
public init(stringLiteral value: String) {
if let d = Double(fromEnglishString: value) {
self = d
} else {
self = 0.0
}
}
}
let doubleFromLiteral: Double = "three"
// doubleFromLiteral is {Some 3.0}
If you want to do exactly what your code example does... Write an extension that implements the StringLiteralConvertible protocol. There's a decent write up on the literal convertibles at NSHipster.
It'd probably look something like this:
extension Double: StringLiteralConvertible {
convenience init(value: String) {
if value == "one" {
self = 1.0
/*
Add more English-to-number conversion magic here
*/
} else {
return NaN
}
}
}
There's a bit more to it than that — StringLiteralConvertible extends a couple of other protocols whose requirements you have to meet, and then there's the whole business of translating English to numbers. You may have a feasibility problem there, but making Doubles from strings is technically possible.
On top of all that, there are more questions as to whether this is a good idea.
Literal initializers can't fail, so you have to return a sentinel value for strings you can't parse a number from. Not very swifty.
Do you actually want to convert string literals, or strings passed in at runtime? The former doesn't seem super useful. The latter requires different syntax at the call site, but lets you make clear that you're defining/using a conversion function.
I'd like to implement a kind of thing which can be uniquely identified, besides, it contains no other fields. It 's kinds of like BasicObject in ruby, or Object in java.
I have added a PartialEq trait.
struct Thing;
impl PartialEq for Thing {
fn eq(&self, other: &Thing) -> bool {
unsafe {
self as *const Thing == other as *const Thing
}
}
}
Now, I want to allow that it can be hashed, and the question is how could I implement Hash trait for a unit struct which has no fileds ? Or, should I add some kind of object_id to it ?
You cannot rely on pointer address to determine for sure unicity of unit structs in Rust, for example the following code will print two times the same address:
struct Foo;
fn main() {
let x = Foo;
let y = Foo;
println!("{}", &x as *const _);
println!("{}", &y as *const _);
}
You need to have them occupy at least one byte in memory, for example by giving them a field that you never use :
struct Thing {
x: u8;
}
impl Thing {
fn new() -> Thing {
Thing { x: 0u8 }
}
}
Then, a simple way would be to continue on the same track as you are going, and using the address of your objects in memory as a base value for the Hash :
use std::hash::{hash,Hash};
use std::hash::sip::SipState;
struct Thing;
impl Hash for Thing {
fn hash(&self, state: &mut SipState) {
let addr = self as *const Thing as u64;
addr.hash(state);
}
}
fn main() {
let f = Thing;
println!("{}", hash(&f));
}
Note : casting &Thing to *const Thing (and then to u64) is not unsafe, so you don't need the unsafe{} block in your implementation of PartialEq.