Define fmt::Display and fmt::Debug together - class

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.

Related

Swift: How to handle optional from Array.randomElement() CS193p 2021

(Non student) attempting 2021 programming assignment 2. I've got the app working with .randomElement, but obviously this allows multiple cards of the same emoji to be generated. I tried removing that element from my areay of emojis, but I can't handle the optional. any extra hints?
Be able to generate cards without duplicates
The following code is what I have so far. Part of it should look familiar from the lectures. my attempt to unwrap doesn't actually compile as shown here. I'm pretty sure I'm close with this..
static func createMemoryGame( chosenTheme : inout EmojiMemoryGame.gameTheme ) -> MemoryGame<String> {
MemoryGame<String>(numberOfPairsOfCards: chosenTheme.themeNoOfPairs) { _ in
var x = chosenTheme.emojis.randomElement()
if let safex = x {
if chosenTheme.emojis.count > 0 {
if let index = chosenTheme.emojis.firstIndex(of: safex ) {
chosenTheme.emojis.remove(at: index)
}//chosenTheme.emojis[pairIndex]
}
}
return safex
}
}

How to access custom derive attributes? [duplicate]

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),
},
]

Parametrized unit tests in Swift

Is there any way to use parameterized unit tests, similar to what you can achieve in .Net using NUnit framework.
[TestCase(12, 3, 4)]
[TestCase(12, 2, 6)]
[TestCase(12, 4, 3)]
public void DivideTest(int expectedResult, int a, int b)
{
Assert.AreEqual(expectedResult, a / b);
}
Using this kind of tests (vs non-parameterized ones) can give you bigger back for buck by allowing you to avoid writing series of almost identical unit tests differing only by parameter values.
I am looking for either XCTest-based solution or some other means to achieve it. Optimal solution should report each test case (parameter set) as a separate unit test in Xcode, so is it clear whether all or only some of the tests cases failed.
The best way to use parametrized is using the XCTestCase subclass's property defaultTestSuite. A clear example with division is the following:
import XCTest
class ParameterizedExampleTests: XCTestCase {
//properties to save the test cases
private var array: [Float]? = nil
private var expectedResult: Float? = nil
// This makes the magic: defaultTestSuite has the set of all the test methods in the current runtime
// so here we will create objects of ParameterizedExampleTests to call all the class' tests methodos
// with differents values to test
override open class var defaultTestSuite: XCTestSuite {
let testSuite = XCTestSuite(name: NSStringFromClass(self))
addTestsWithArray([12, 3], expectedResult: 4, toTestSuite: testSuite)
addTestsWithArray([12, 2], expectedResult: 6, toTestSuite: testSuite)
addTestsWithArray([12, 4], expectedResult: 3, toTestSuite: testSuite)
return testSuite
}
// This is just to create the new ParameterizedExampleTests instance to add it into testSuite
private class func addTestsWithArray(_ array: [Float], expectedResult: Float, toTestSuite testSuite: XCTestSuite) {
testInvocations.forEach { invocation in
let testCase = ParameterizedExampleTests(invocation: invocation)
testCase.array = array
testCase.expectedResult = expectedResult
testSuite.addTest(testCase)
}
}
// Normally this function is into production code (e.g. class, struct, etc).
func division(a: Float, b: Float) -> Float {
return a/b
}
func testDivision() {
XCTAssertEqual(self.expectedResult, division(a: array?[0] ?? 0, b: array?[1] ?? 0))
}
}
You function parameters are all over the place. I'm not sure if your function is doing multiplication or division. But here's one way you can do multiple test cases in a single test method.
Given this function:
func multiply(_ a: Int, _ b: Int) -> Int {
return a * b
}
You can have multiple test cases on it:
class MyTest: XCTestCase {
func testMultiply() {
let cases = [(4,3,12), (2,4,8), (3,5,10), (4,6,20)]
cases.forEach {
XCTAssertEqual(multiply($0, $1), $2)
}
}
}
The last two would fail and Xcode will tell you about them.
The best way to handle parameterized testing is to use XCTContext.runActivity. This allows to create a new activity with some name that will help you identify exactly which of the iterations failed. So for your division scenario:
func testDivision() {
let testCases = [
(a: 12, b: 3, result: 4),
(a: 12, b: 2, result: 6),
(a: 12, b: 6, result: 1),
(a: 12, b: 4, result: 3),
]
for (a, b, result) in testCases {
XCTContext.runActivity(named: "Testing dividing \(a) by \(b) to get result \(result)") { activity in
XCTAssertEqual(result, a/b)
}
}
}
Note that after running the above test, case no. 1, 2 and 4 will succeed while case no. 3 will fail. You can view exactly which test activity failed and which of the assertions caused faiure in test report:
I rather like #DariusV's solution. However, it doesn't handle well when I the developer execute the test method directly from Xcode's sidebar. That's a dealbreaker for me.
What I wound up doing I think is rather slick.
I declare a Dictionary of testValues (probs need a better name for that) as an instance computed property of my XCTestCase subclass. Then, I define a Dictionary literal of inputs keying expected outputs. My example tests a function that acts on Int, so I define testValues like so:
static var testRange: ClosedRange<Int> { 0...100 }
var testValues: [Int: Int] {
let range = Self.testRange
return [
// Lower extreme
Int.min: range.lowerBound,
// Lower bound
range.lowerBound - 1: range.lowerBound,
range.lowerBound : range.lowerBound,
range.lowerBound + 1: range.lowerBound + 1,
// Middle
25: 25,
50: 50,
75: 75,
// Upper bound
range.upperBound - 1: range.upperBound - 1,
range.upperBound : range.upperBound,
range.upperBound + 1: range.upperBound,
// Upper extreme
Int.max: range.upperBound
]
}
Here, I very easily declare my edge and boundary cases. A more semantic way of accomplishing the same might be to use an array of tuples, but Swift's dictionary literal syntax is thin enough, and I know what this does. 😊
Now, in my test method, I have a simple for loop.
/// The property wrapper I'm testing. This could be anything, but this works for example.
#Clamped(testRange) var number = 50
func testClamping() {
let initial = number
for (input, expected) in testValues {
// Call the code I'm testing. (Computed properties act on assignment)
number = input
XCTAssertEqual(number, expected, "{number = \(input)}: `number` should be \(expected)")
// Reset after each iteration.
number = initial
}
}
Now to run for each parameter, I simply invoke XCTests in any of Xcode's normal ways, or any other way that works with Linux (I assume). No need to run every test class to get this one's parameterizedness.
Isn't that pretty? I just covered every boundary value and equivalence class in only a few lines of DRY code!
As for identifying failing cases, each invocation runs through an XCTAssert function, which as per Xcode's convention will only throw a message at you if there's something wrong that you need to think about. These show up in the sidebar, but similar messages tend to blend together. My message string here identifies the failing input and its resulting output, fixing the blending-togetherness, and making my testing flow a sane piece of cherry apple pie. (You may format yours any way you like, bumpkin! Whatever blesses your sanity.)
Delicious.
TL;DR
An adaptation of #Code Different's answer: Use a dictionary of inputs and outputs, and run with a for loop. 😄
#Code Different's answer is legit. Here's other two options, or rather workarounds:
Property Based Testing
You could use a tool like Fox to perform generative testing, where the test framework will generate many input sets for the behaviour you want to test and run them for you.
More on this approach:
http://www.pivotaltracker.com/community/tracker-blog/generative-testing
http://blog.jessitron.com/2013/04/property-based-testing-what-is-it.html
BDD Shared Examples
If you like the BDD style and are using a test framework that supports them, you could use shared examples.
Using Quick it would look like:
class MultiplySharedExamplesConfiguration: QuickConfiguration {
override class func configure(configuration: Configuration) {
sharedExamples("something edible") { (sharedExampleContext: SharedExampleContext) in
it("multiplies two numbers") {
let a = sharedExampleContext()["a"]
let b = sharedExampleContext()["b"]
let expectedResult = sharedExampleContext()["b"]
expect(multiply(a, b)) == expectedResult
}
}
}
}
class MultiplicationSpec: QuickSpec {
override func spec() {
itBehavesLike("it multiplies two numbers") { ["a": 2, "b": 3, "result": 6] }
itBehavesLike("it multiplies two numbers") { ["a": 2, "b": 4, "result": 8] }
itBehavesLike("it multiplies two numbers") { ["a": 3, "b": 3, "result": 9] }
}
}
To be honest this option is: 1) a lot of work, 2) a misuse of the shared example technique, as you are not using them to test behaviour shared by multiple classes but rather to parametrise the test. But as I said at the start, this is a more of a workaround.
The asserts all seem to throw, so perhaps something like this will work for you:
typealias Division = (dividend: Int, divisor: Int, quotient: Int)
func testDivisions() {
XCTAssertNoThrow(try divisionTest((12, 3, 4)))
XCTAssertNoThrow(try divisionTest((12, 2, 6)))
XCTAssertNoThrow(try divisionTest((12, 4, 3)))
}
private func divisionTest(_ division: Division) throws {
XCTAssertEqual(division.dividend / division.divisor, division.quotient)
}
If one fails, the entire function will fail. If more granularity is required, every case can be split up into an individual function.
We found that this solution How to Dynamically add XCTestCase offers us the flexibility we need. Being able to dynamically add tests, pass arguments to tests, and display the dynamic test names in the test report.
Another option is to checkout XCTestPlan in XCode. There's an informative video from WWDC about it.

How to enforce that a type implements a trait at compile time?

I want to write a macro like this:
macro_rules! a {
( $n:ident, $t:ty ) => {
struct $n {
x: $t
}
}
}
But $t should implement Add, Sub and Mul traits. How can I check it at compile-time?
First, solve the problem without macros. One solution is to create undocumented private functions that will fail compilation if your conditions aren't met:
struct MyType {
age: i32,
name: String,
}
const _: () = {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
// RFC 2056
fn assert_all() {
assert_send::<MyType>();
assert_sync::<MyType>();
}
};
Then, modify the simple solution to use macros:
macro_rules! example {
($name:ident, $field:ty) => {
struct $name {
x: $field,
}
const _: () = {
fn assert_add<T: std::ops::Add<$field, Output = $field>>() {}
fn assert_mul<T: std::ops::Mul<$field, Output = $field>>() {}
// RFC 2056
fn assert_all() {
assert_add::<$field>();
assert_mul::<$field>();
}
};
};
}
example!(Moo, u8);
example!(Woof, bool);
In both cases, we create a dummy const value to scope the functions and their calls, avoiding name clashes.
I would then trust in the optimizer to remove the code at compile time, so I wouldn't expect any additional bloat.
Major thanks to Chris Morgan for providing a better version of this that supports non-object-safe traits.
It's worth highlighting RFC 2056 which will allow for "trivial" constraints in where clauses. Once implemented, clauses like this would be accepted:
impl Foo for Bar
where
i32: Iterator,
{}
This exact behavior has changed multiple times during Rust's history and RFC 2056 pins it down. To keep the behavior we want in this case, we need to call the assertion functions from another function which has no constraints (and thus must always be true).

How to do `Hash` to a unit struct in rust?

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.