Creating code based on value of macro agrument rust - rust

macro_rules! retry_put {
($mod_name:ident, $data_type:ty) => {{
fn $mod_name() {
// somelike
if $mod_name == "red" {
// generate code written here and not the one in else block
return u8;
}
else {
// generate code written here and not the one in if
return "string";
}
}
}
}
I am tring to change the return type based on input basically, if input is true return string else return int.
Or maybe give example for :
give example where we are accepting a arguement in macro and if its even calulate factorial of 5 and return it as integer and if the agruement is odd calculate the factoreial of 5 and return it as string. And name of both functions should be same. and logic of calculating 5! should not be repeated.

You can overload a macro like this:
macro_rules! retry_put {
(red, $data_type:ty) => {{
fn red() {
return u8;
}
}
}
($mod_name:ident, $data_type:ty) => {{
fn $mod_name() {
return "string";
}
}
}
}
See macro_rules!.

Related

Vala, string to enum

Is there a way to convert a string to an enum in vala:
string foo = "Enum1";
MY_ENUM theEnum = MY_ENUM.get_value_by_name(foo);
enum MY_ENUM {
Enum1,
Enum2,
Enum3
}
So in this example "theEnum" would have the value: MY_ENUM.Enum1
It is possible using the runtime type system provided by GLib's GObject library. There are EnumClass and EnumValue. These provide introspection at runtime and allow an enum to be initialised from a string.
The syntax is a bit complex at present, although it may be possible for someone to modify the Vala compiler to make it easier, but that is a significant piece of work.
An example:
void main () {
try {
MyEnum? the_enum_value;
the_enum_value = MyEnum.parse ("FIRST");
print (#"$(the_enum_value)\n");
} catch (EnumError error) {
print (#"$(error.message)\n");
}
}
errordomain EnumError {
UNKNOWN_VALUE
}
enum MyEnum {
FIRST,
SECOND,
THIRD;
public static MyEnum parse (string value) throws EnumError {
EnumValue? a;
a = ((EnumClass)typeof (MyEnum).class_ref ()).get_value_by_name ("MY_ENUM_" + value);
if (a == null) {
throw new EnumError.UNKNOWN_VALUE (#"String $(value) is not a valid value for $(typeof(MyEnum).name())");
}
return (MyEnum)a.value;
}
}

Expanding a recursive macro in rust, similar to serde_json but for HTML elements

#[macro_export]
macro_rules! reactant {
// Converts (function) {...} into element
( $f:ident $t:tt ) => {
{
let mut elem = HtmlElement::new($f);
reactant!(#expand elem $t);
elem
}
};
// Expands {...} and parses each internal node individually
( #expand $self:ident { $($t:tt),* } ) => {
$(
reactant!(#generate $self $t);
)*
};
// Takes a (function) {...} node, feeds it back recursively, and pushes it into parent
( #generate $self:ident $t1:tt $t2:tt) => {
{
$self.push_inner(reactant!($t1 $t2));
}
};
// Takes a literal and sets the parent internal to a string
( #generate $self:ident $l:literal) => {
{
$self.set_inner(String::from($l)).unwrap();
}
};
}
#[allow(unused_macros)]
#[cfg(test)]
mod tests {
use crate::html::types::*;
use crate::html::HtmlElement;
use crate::reactant;
#[test]
fn test() {
// Doesn't work, not expecting '{' after second div, although the first one works fine
let x = reactant!(div {
div {
"test"
}
});
// Works, outputs <div>thing</div>
let y = reactant!(div {
"hello",
"thing"
});
}
}
I am working on making an uncreatively named HTML library in Rust, and am also learning macros at the same time (the macro documentation is confusing). Part of the project is making a macro that generates HTML elements recursively to make a document, in a similar appearance to serde_json. The syntax is shown in the test cases. Basically, every HTML element (div, h1, etc.) is mapped to a function that outputs a struct that I have crafted for HTML elements. I managed to get the macro working in one way, but it only allowed for HTML children when I want it to also take literals to fill in, say, an h1 with a string (test case 1). Test case 2 shows where it doesn't work, and I am not understanding why it can't read the {.
Let's try to trace what happens when the macro is being expanded:
reactant!(div { div { "test" } });
This triggers the first rule: $f:ident $t:tt with:
$f set to div
$t set to { div { "test" } }
Which gets expanded to:
reactant!(#expand elem { div { "test" } });
I believe you intended the second step to trigger rule number 2: #expand $self:ident { $($t:tt),* } with:
$self set to elem
$t set to div { "test" }
Which would get expanded to:
reactant!(#generate elem div { "test" });
But div { "test" } is actually two tts and so can't be parsed by this rule (or by any other rule).
If my interpretation of your intentions is correct, you will need to have separate rules to handle each case and process the list iteratively:
// Expands {...} and parses each internal node individually
( #expand $self:ident { $t1:tt $t2:tt, $($tail:tt)* } ) => {
reactant!(#generate $self $t1 $t2);
reactant!(#expand $self { $($tail)* })
};
( #expand $self:ident { $t:tt, $($tail:tt)* } ) => {
reactant!(#generate $self $t);
reactant!(#expand $self { $($tail)* });
};
// Duplicate rules to handle the last item if it's not followed by a ","
( #expand $self:ident { $t1:tt $t2:tt } ) => {
reactant!(#generate $self $t1 $t2);
};
( #expand $self:ident { $t:tt } ) => {
reactant!(#generate $self $t);
};
Playground

How to validate option parameter value from the struct

I am working on rust-lang facing issue when i am trying do validation on option parameter during the updating. Below is demo version of code. Please do help me. Better to use match pattern or if condition statement.
#[derive(Deserialize)]
struct UserUpdateReq {
uuid: Option<i32>,
first_name: Option<String>,
last_name: Option<String>,
}
fn update_user(req: Json) => Result<Response<Vec<i32>>, String>{
let req: UserUpdateReq = try_s!(json::from_value(req));
// Here I need to validate optional parameters
// checking both parameters have a value. In case both are None, return err message
// if any one value is present update that value.
}
If you want to check that at least one of first_name and last_name are provided, you can do it on a case-by-case basis with:
match (req.first_name, req.last_name) {
(Some(first_name), Some(last_name)) => {
// update both
}
(None, Some(last_name)) => {
// update last name
}
(Some(first_name), None) => {
// update first name
}
(None, None) => {
// error
}
Or
if req.first_name.is_none() && req.last_name.is_none () {
// error
} else {
if let Some(first_name) = req.first_name {
// update first name
}
if let Some(last_name) = req.last_name {
// update last name
}
}

How to conditional statements in action output in Bixby

Hi I want to go to another action by putting a conditional statement in the action output.
What should I do?
For example
action (~~) {
description (Validate items passed from javascript)
collect {
input (~~) {
type (~~)
min (~~) max (~~)
}
}
type(~~~)
output (items){
on-empty(items.item1){ // if items.item1 is empty.
replan { // go to case1Action.
intent {
goal : case1Action
value : ~~~~~
}
}
}else{ // else
replan { // go to case2Action.
intent {
goal : case2Action
value : ~~~~~
}
}
}
}
or I want to select the view according to the output value.(Actually this is the purpose of the question)
output (items){
if(items.item1 == "goFirstCase"){
// First case view
}else{
// Second case view
}
}
I think by "select a different view according to the output value" I presume you mean you want to change what shows on the screen? because a "view" actually is comprised of the dialog, layout, and conversation-drivers.
https://bixbydevelopers.com/dev/docs/dev-guide/developers/building-views.views
For majority of use cases, there's really only one result-view that will be used, and any of the three contents of a view can be changed based on your preferred conditions as the above answer suggests.
within a view you can have the three different components defined with these three blocks: message for dialog, render for layout, and conversation-drivers
using your example,
//in a result-view
message {
if (items.item1 == "firstCase") {
template-macro (firstCase-result-dialog) {//enter params}
}
}
render {
if (size(items) > 1) {
list-of (items) {
where-each (item) {
if (item == "firstCase") {
layout-match (item) {
mode (Summary)
}
// OR use layout-macro
layout-macro (firstCase-result-summary-thumbnail-card) {//enter params}
}
}
}
}
}
similar conditional work can be done on conversation-drivers of course.
In your case, you would not need on-empty in action, but use template-macro-def as briefly explained in https://corp.bixbydevelopers.com/dev/docs/dev-guide/developers/refining-dialog.dialog-macros
// template file one
template-macro-def (id1) {
params {
param (x) {
Type (Items) ....
}
// template file two
template-macro-def (id2) {
// param x is type Items
}
//view file
result-view {
match: Items(this)
// after some checking make sure is single item
// it is possible to use other condition like if (this.sub1 == 2)
if (exists(this.sub1)) {
template-macro (id1) {
param (x) { expression (this) }
}
}
else {
template-macro (id2) {
param (x) { expression (this) }
}
}
The above would be the recommended way to handle different views for same concept in Bixby.
on-empty in action would be used for the purpose of either replan or relax some search condition in order to avoid 0 result. Bixby does not support on-empty(key) {} syntax according to https://corp.bixbydevelopers.com/dev/docs/reference/type/action.output.on-empty and on-empty would only apply in your case if output(items) itself is empty and would not check any sub-property of items.
Another option.
instead to use 'on-empty' block, you can use 'throws - error'
in action model,
output (items) {
throws {
error (case1ActionError) {
on-catch {
replan {
intent {
goal : case1Action
value : ~~~~~
}
}
}
}
error (case2ActionError) {
on-catch {
replan {
intent {
goal : case2Action
value : ~~~~~
}
}
}
}
}
}
And, in js code,,
if (error condition1) {
throw fail.checkedError('case 1 error', 'case1ActionError')
} else if (error condition2) {
throw fail.checkedError('case 2 error', 'case2ActionError')
}
For fail, refer to https://bixbydevelopers.com/dev/docs/reference/JavaScriptAPI/fail#failcheckederrormessage-errorid-errorobj

How do I used the colored crate with non-static strings?

I am making a connect 4 game where I want to print colored text on the terminal window using the colored crate.
I am checking to see if there is a symbol in the table to print like this:
for row in &self.board {
for symbol in row {
if let Some(s) = symbol {
print!("\t[{}]", s);
} else {
print!("\t[ ]");
}
}
println!("\n");
}
When I want to turn the letters to red, it does not work unless it is a static string.
I tried doing this but it doesn't work:
for row in &self.board {
for symbol in row {
if let Some(s) = symbol {
print!("\t[{}]".red(), s);
} else {
print!("\t[ ]");
}
}
println!("\n");
}
You can not use the color methods on the format string, which is required to be a string literal by the compiler. You have to use it on the arguments. Like this:
for row in &self.board {
for symbol in row {
if let Some(s) = symbol {
print!("\t[{}]", s.red());
} else {
print!("\t[ ]");
}
}
println!("\n");
}

Resources