I have a SQL query that returns a column with the BigDecimal type but my domain model works with f64:
price: Price::new(record.price).unwrap(),
^^^^^^^^^^^^
rustc: mismatched types
expected `f64`, found struct `BigDecimal`
How can I convert BigDecimal type into f64?
I was able to fix this problem by following steps
Add bigdecimal crate to the project (cargo add bigdecimal)
Add use bigdecimal::ToPrimitive; to the top of the file where I want to convert types.
use .to_f64() method on my BigDecimal instance
use bigdecimal::ToPrimitive;
...
price: Price::new(record.price.to_f64().unwrap()).unwrap()
...
The to_f64() method appeared on the BigDecimal type
Related
BigUint::from(24u32)
I understand that it is related to a big unsigned integer since it is part of a cryptography module to factor big numbers. I don't understand what the part from(24u32) does.
For example, if it is used in this context
let b: BigUint = (BigUint::from(24u32) * &n).sqrt() + &one;
Conversions between types in Rust are defined by the From trait which defines a function from, so that Foo::from (bar) converts the value bar to the type Foo. In your case, you are therefore converting 24u32 to type BigUint, but what's this 24u32?
Integer literals in Rust can use a suffix to specify their actual type. If you wrote just 24, it could be for example an i32, a u8 or a u32. Most of the time the compiler is able to infer the actual type from the way the value is used, and when it can't it defaults to i32. But in your case that won't work: there is no BigUint::from<i32> but there are conversion functions for all the regular unsigned types: u8, u16, u32, u64 and u128, so the compiler doesn't know which one to use. Adding the u32 suffix clarifies the type, so 24u32 is the value 24 with the type u32, allowing the compiler to understand that you want BigUint::from<u32> (24).
The BigUint struct implements the From<u32> trait, which means that it will implement a from(u32) function.
Implementations of the From<_> trait are used to perform a value conversion that will consume the original input. In your example the BigUint struct is constructed from the 24u32 number.
I'd like to do a count on records of a table named topics. I'm doing it almost by the book
but when I do
let count: u64 = topics.select(count_star()).first(&conn).unwrap();
I keep getting (.first is underlined as error):
[rustc E0277] [E] the trait bound `u64: diesel::deserialize::FromSql<diesel::
sql_types::BigInt, diesel::mysql::Mysql>` is not satisfied
the trait `diesel::deserialize::FromSql<diesel::sql_types::BigInt, diesel::
mysql::Mysql>` is not implemented for `u64`
help: the following implementations were found:
<u64 as diesel::deserialize::FromSql<diesel::sql_types::
// I guess there's more information but Vim's
// Pmenu only shows up to eight lines.
So propably I need to do some type casting here, but honestly, I have no idea at which point.
As the error tells you, count_star generates a BigInt.
And as BigInt's documentation indicates, BigInt is convertible to and from i64, not u64.
I guess despite MySQL having unsigned integers Diesel doesn't support them because SQL doesn't specify unsigned integers, so not all database engines have them (e.g. Postgres does not).
Anyway your count should be an i64, or you need to set up a more explicit conversion from a BigInt to an i64 to an u64.
I want to traverse through a file tree and save the file and directory names in a nested HashMap. How do I define such a nested HashMap?
Something like this doesn't compile:
type NestedHashMap = HashMap<String, HashMap>;
It throws:
error[E0107]: wrong number of type arguments: expected at least 2, found 0
--> src/lib.rs:3:38
|
3 | type NestedHashMap = HashMap<String, HashMap>;
| ^^^^^^^ expected at least 2 type arguments
Rust is a statically typed language, so you need to tell the compiler in advance the exact type of the elements in your HashMap. Since each entry can be either a file name or another HashMap, the easiest solution is to use an enum type:
enum Entry {
File(String),
Directory(HashMap<String, Entry>),
}
This allows you to model arbitrary nesting.
Scala's value classes provide a way to use the type system without allocating runtime objects (structs in case of Rust). I'm looking for an equivalent in Rust.
The use case I'd like to cover is passing around a string that represents a URI, by annotating relevant signatures with something like Uri instead of String, and, ideally, use this Uri when a String is expected. All this with minimal overhead.
An obvious solution would be to use structs with one field:
struct Uri { val: String }
This has the drawback of slightly awkward usage, not being acceptable where a String is expected, and I'm unsure of its overhead.
Is there something similar to Scala's value classes in Rust? Is there some other mechanism that facilitates this use case?
I believe the thing you are looking for is the "strong type system". In Rust it is represented with a tuple struct with one field (a newtype):
struct Uri(pub String);
This creates a strong type with the least overhead. I'd say this just creates a mark for the compiler that this type is Uri and nothing else. Since this is a strong type, you can't simply pass String to it and get a String from it, you must do a conversion manually.
Simple example gives you a strong type on top of the String:
struct Uri(pub String);
fn takes_uri(uri: Uri) {
println!("URI: {}", uri.0);
}
fn takes_string(uri: String) {
println!("String: {}", uri);
}
fn main() {
let uri = Uri("https://stackoverflow.com".to_owned());
takes_uri(uri);
// takes_string(uri); // This does not compile
}
The key thing with strong types is that you can not implicitly cast them so this requires the code writer to write explicit code.
package main
type foo struct {
bar string
baz string
}
func (f foo) String() string {
return f.bar + " " + f.baz
}
func main() {
f := foo{"hello", "world"}
v := string(f)
}
This outputs main.go:14: cannot convert f (type foo) to type string.
So it would seem that casting something to a string does not look at the stinger interface. My guess is that this is because casting is implemented on a lower level than the stringer interface and it's impossible/hard to mix the two, but I'm not sure. Can anyone shed any light on this?
Also, since this is not possible, what would be idiomatic way to convert my struct to a string in this case? Do I just call .String() myself, or fmt.Sprintf("%s", f), or something else?
There is no casting in Go, there is type Conversion and Type assertion.
What you're doing (T(Expression)) is a conversion and it has strict rules when it can be used and what the result will be.
There are specific rules applied to Conversions to and from a string type. So what you want cannot be achieved with type conversion.
The simplest and preferred way would be to call the method yourself:
v := f.String()
fmt.Sprintf() would be just an unnecessary overhead and complication if your struct already implements Stringer. But if you don't have guarantee for this, then yes, fmt.Sprintf() would be the general way.
You could ask why?
In the specification level the type conversion expression is not defined as the result of a custom/user made function or method. The Stringer interface (type Stringer interface{String() string}) is not even a built-in type in contrast to the error interface.
But despite the fact that Stringer is not a built-in type, it is still present in some packages (for example in fmt.Stringer) and is checked by various methods or functions (e.g. fmt.Printf() and relatives).