Unwrap Struct Once And Modify Multiple Values - rust

I have the following code:
((&self.items).get(&self.lastIndex)).unwrap().val1 = "hello";
((&self.items).get(&self.lastIndex)).unwrap().val2 = "world";
Map of ink storage. How can I unwrap the struct from KV once and modify all values at once? Like so:
/// not rust syntax
((&self.items).get(&self.lastIndex))
.unwrap()->{
this.val1 = "";
this.val2 = "";
}

Related

I am getting an error trying to use the end function to find the end of a string

extern crate regex;
use regex::Regex;
fn main() {
/* Input for testing*/
let text = "definitions:\n\ta = point(3,3); \n\td = point(9,4);\n\tx = circle(a,1);\n\ty = square(d,2)\n
operations:\n\tprint(x);\n\tprint(y);\n\tintercts(x,y)\nend.";
let def_regex = Regex::new(r"^definitions").unwrap();
let ws_regex = Regex::new(r"^ ").unwrap();
while data.chars().count() > 0 {
if ws_regex.is_match(&data) {
data = data.chars().skip(1).collect();
continue;
}
if def_regex.is_match(&data) {
let pos = def_regex.find(&data).unwrap();
data = data.chars().skip(pos.end()).collect();
println!("DEFINITIONS");
continue;
}
}
}
The error code I am getting is:
error[E0599]: no method named end found for tuple (usize, usize) in the current scope
I am very new to rust and think it might be a simple fix, but cannot seem to figure it out.

Is there way to cut iterator by another iterator in rust?

I want to cut the iterator by another. Pictorial example:
let it = non_sliceable_container.iter();
while predicate(it.next(), ...) {
// ...
}
let prefix = non_sliceable_container.iter().set_end(it); // <- want something like this
for val in prefix {
// ...
}
/*
works as
let prefix = container.iter();
while prefix != it {
let val = prefix.next();
// ...
}
*/
It seems possible because only immutable references are present.
So you're wanting to move it while some predicate is true, and then iterate from the beginning of the container to where it is? You should just be able to iterate with take_while:
for val in container.iter().take_while(predicate) {
// ..
}
Seems that I misunderstood rust's iterators: I thought that it's possible to compare iterators like in c++ (e.g. check if it's iterators of the same container and on same position). It's not true. So the solution to this situation is following:
let it = non_sliceable_container.iter();
let counter = 0usize;
while predicate(it.next(), ...) {
// ...
counter += 1;
}
let prefix = non_sliceable_container.iter().take(counter);
for val in prefix {
// ...
}

How to conditionally create a serializer and sequence? (Option<SerializeSeq>)

I'm trying to process data from a channel, so the whole structure can't be serialized at once. In fact it won't all fit in memory. The trouble I'm running into is that I can't create an Option<SerializeSeq> because that object depends on Serializer (which doesn't live long enough). I'd like to initialize them both together, or not at all:
use serde::ser::{SerializeSeq, Serializer};
fn process_stream(output: bool) -> serde_json::Result<()> {
let rows = /* whatever iterator */ "serde".chars();
let mut seq = if output {
let out = std::io::stdout();
let mut ser = serde_json::Serializer::new(out);
let seq = ser.serialize_seq(None)?
Some(Ok(seq))
} else {
None
}.transpose()?;
for row in rows {
//process_data(row);
if let Some(seq) = &mut seq {
seq.serialize_element(&row)?;
}
}
if let Some(seq) = seq {
seq.end()?;
}
Ok(())
}
(Original code snippet from here.)
The problem is: ser does not live long enough. But I don't want to initialize ser in the outer scope because it may not be enabled (and its writer would create or truncate a file that should not be created). I tried returning ser and seq as a tuple. I tried putting them together in a helper struct, but I couldn't figure out all the template parameters and lifetimes.
How can serde serializer and sequence be initialized based on a condition and stored in Option?
Make sure that ser doesn't get dropped prematurely by declaring it outside the if body:
let mut ser;
let mut seq = if output {
let out = std::io::stdout();
ser = serde_json::Serializer::new(out);
let seq = ser.serialize_seq(None)?;
Some(Ok(seq))
} else {
None
}.transpose()?;

How to get any type of parms in rust

I added the read_input crate to my dependencies and wrote the following code:
let username: String = input().repeat_msg("Please input your name: ").get();
When I try to print it in the terminal, it prints what I've inputted, but when I try to consume it through a function:
pub fn sub(values: String) {
// code
}
I can't take it in, it says I've given it a () type variable when it explicitly says in the top String, so I was wondering if I can maybe get the text out of the input some how by converting or some way, or in the function being able to get any type of params.
So I want to know a way to get any type of params in a function, it can be a i32 or a String or how to convert the () type variable to String.
full code
maint.rs:
use read_input::prelude::*;
mod sub;
use sub::lexar;
fn main() {
println!("Welcome Rice Lang");
let mut done = false;
let ctrldkey = false;
while !done {
let mut input: String = input().msg("> ").get();
println!("{}", input);
if ctrldkey == true {
done = true;
}
}
}
sub.rs:
pub fn sub(values: String) {
print!("{}", values)
}
Error:
input = sub(input);
^^^^^^^^^^^^ expected struct `String`, found `()`
The problem you are having is not that you are unable to call the function. If you were to try to do this instead:
sub(input);
Then it would work. Which means you can call the function. The problem is that you are trying to assign to input what the function returns. But the function returns nothing also known as (). And the input variable is actually a String so you can only put a String to it.
Example of assigning wrong type to a variable will give a similar error as you got:
let mut input = String::from("example string");
// this gives an error because we are trying to
// put a non-String value into input
input = 6;
To have a function that returns a type other than () (which is the default) you have to specify the return type like so:
fn this_returns_a_string() -> String {
String::from("from function")
}
let mut input = String::from("example string");
// this will work
input = this_returns_a_string();

How to get a value from a Result?

How can I get the value of a struct which is returned in a Result from another function? Example below.
#[derive(Debug)]
pub struct Keypair(ed25519_dalek::Keypair);
pub fn keypair_from_seed(seed: &[u8]) -> Result<Keypair, Box<dyn error::Error>> {
let dalek_keypair = ed25519_dalek::Keypair { secret, public };
Ok(Keypair(dalek_keypair))
}
fn main(){
//here seed_bytes is mnemonics
let sk = keypair_from_seed(&seed_bytes);
//sk contains the secret key and public key, i want to extract it different secret key & public key
}
If you feel very confident
let sk = keypair_from_seed(&seed_bytes).unwrap();
or
let sk = keypair_from_seed(&seed_bytes).expect("my own failure message");
However, it is recommended to proceed like this
if let Ok(sk) = keypair_from_seed(&seed_bytes) {
// ... use sk ...
} else {
// ... sk is not available, may be should
// we warn the user, ask for an alternative ...
}
or, if you want to explicitly handle the error
match keypair_from_seed(&seed_bytes) {
Ok(sk) => {
// ... use sk ...
},
Err(e) => {
// ... sk is not available, and e explains why ...
},
}
Note that, if the function containing these lines is also
able to return an error, you can just propagate it with
the ? notation (if the error returned by
keypair_from_seed() is convertible into the error returned
by your function)
let sk = keypair_from_seed(&seed_bytes)?;
see
unwrap,
expect,
if let,
match,
?
Lets look the definition of Result in Rust documentation
enum Result<T, E> {
Ok(T),
Err(E),
}
So a Result is either Ok which contains a value with type T, or Err which contains a value with type E.
You have couple options to extract the value.
1- result.unwrap() or result.expect("error message")
This function returns the Ok value if result is Ok or panics the program (program is terminated). If you are sure that it doesn't contain error or you just want to write the correct case first and deal with error handling later it makes sense but you shouldn't use it all the time since it directly crashes the app when the value is not Ok.
You can use it like this
let val = result.unwrap();
// or
let val = result.expect("oops not Ok");
Only difference of expect you can provide the error message yourself instead of the standard error message of unwrap.
2- Pattern matching
In Rust, pattern matching is used for enum types so that user can do the necessary thing based on the current variant of the enum. You can use it like this
match result {
Ok(val) => {
// Use val here....
},
Err(err) => {
// Do something with the error if you want
}
}
If you are going to handle only one variant, you can also use if let statement like this
if let Some(val) = result {
// Do something with val
}
The returned result from the function is of the type Result<Keypair, Box<dyn error::Error>>.
There are multiple ways to extract a result from the Result container. Basically rust wants you to check for any errors and handle it. If no errors, you can extract the result and use it.
if let Ok(sk) = keypair_from_seed(&seed) {
let public = sk.0.public;
let secret = sk.0.secret;
/* use your keys */
}
Notice the sk.0 since you are using a struct of a tuple type. If your struct had multiple variables, something like
pub struct KeyTuple(ed25519_dalek::Keypair, i32, &str);
You would have used it as
let kt = keytuple_from_seed(&seed).unwrap();
let kp: ed25519_dalek::Keypair = kt.0;
let le: i32 = kt.1;
let st: &str = kt.2;

Resources