pub enum MyEnum{
Int(i32),
Float(f32)
}
fn convert(my_vec:Vec<i32>) -> Vec<MyEnum>
{
//??
}
I need to convert a vector of ints to a vector of enum type Int.
A simple map() + collect() will do:
my_vec.iter().map(|v| MyEnum::Int(*v)).collect::<Vec<_>>()
// Or
my_vec.iter().copied().map(MyEnum::Int).collect::<Vec<_>>()
Related
I'm trying to deserialize the following API response (for simplicity, I'll only copy two slices of the array, but it will be bigger in reality). The code is oversimplified to demonstrate the example.
API response:
[[1609632000000,32185,32968,34873,31975,18908.90248876],[1609545600000,29349.83250154,32183,33292,29000,22012.92431526]]
So it's a big array/vector, composed of arrays/vectors with six integer OR floats (their position will also vary).
For this, I'm trying to use the generics , but it seems I'm missing something since I cannot get it to compile..
it is failing with
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: reqwest::Error { kind: Decode, source: Error("invalid type: integer `1609632000000`, expected struct T", line: 1, column: 15) }'
use blocking::Response;
use serde::{Deserialize, Serialize};
use reqwest::{blocking, Error, StatusCode};
struct allData<T> {
data: Slice<T>
}
#[derive(Debug, Serialize, Deserialize)]
struct Slice<T>{
data1: T,
data2: T,
data3: T,
data4: T,
data5: T,
data6: T,
}
fn get_data() -> Option<Slice> /*I know the signature is not correct, read until the end for the correct one*/ {
let url = format!("{}", my_url_string);
let response: Slice<T> = blocking::get(&url).unwrap().json().unwrap();
Some(response);
}
fn main() {
let call_the_api = get_data();
println!("{:?}", call_the_api);
}
What would be the correct way to use a Struct with generics that can return a vector of "Slice".
ie.
Vector{
Slice {
data1,
data2,
data3,
data4,
data5,
data6,
},
Slice {
data1,
data2,
data3,
data4,
data5,
data6,
}
}
The derivation of Deserialize on your Slice struct does not work on a JSON array, instead it expects a JSON dict with fields data1, data2 and so on. Presumably, you don't want to manually implement the Deserialize trait for your type, so you'll want a Vec<Vec<T>> to model your nested arrays:
#[derive(Deserialize)]
#[serde(transparent)]
struct AllData<T>(Vec<Vec<T>>);
This type restricts all items in the Vec to be of type T. This means, you don't get to use some f64 and some i64, it'll either be all floats or all ints. To make this wrapper generic over both floats and ints, you'll probably want some enum:
#[derive(Deserialize)]
// note, this causes deserialization to try the variants top-to-bottom
#[serde(untagged)]
enum FloatOrInt {
Int(i64),
Float(f64),
}
With the enum, the type parameter T on AllData is not needed anymore, you can go for:
#[derive(Deserialize)]
#[serde(transparent)]
struct AllData(Vec<Vec<FloatOrInt>>);
If you are sure that the inner array has always length 6, you can replace it with an array: [FloatOrInt; 6].
Putting it together, you'd get something like this:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=52bd3ce7779cc9b7b152c681de8681c4
I'm given a data-format that includes a sequence of objects with exactly one named field value each. Can I remove this layer of indirection while deserializing?
When deserializing, the natural representation would be
/// Each record has it's own `{ value: ... }` object
#[derive(serde::Deserialize)]
struct Foobar<T> {
value: T,
}
/// The naive representation, via `Foobar`...
#[derive(serde::Deserialize)]
struct FoobarContainer {
values: Vec<Foobar<T>>,
}
While Foobar adds no extra cost beyond T, I'd like to remove this layer of indirection at the type-level:
#[derive(serde::Deserialize)]
struct FoobarContainer {
values: Vec<T>,
}
Can Foobar be removed from FoobarContainer, while still using it using deserialization?
In the general case, there's no trivial way to make this transformation. For that, review these existing answers:
How do I write a Serde Visitor to convert an array of arrays of strings to a Vec<Vec<f64>>?
How to transform fields during deserialization using Serde?
The first is my normal go-to solution and looks like this in this example.
However, in your specific case, you say:
objects with exactly one named field value
And you've identified a key requirement:
While Foobar adds no extra cost beyond T
This means that you can make Foobar have a transparent representation and use unsafe Rust to transmute between the types (although not actually with mem::transmute):
struct FoobarContainer<T> {
values: Vec<T>,
}
#[derive(serde::Deserialize)]
#[repr(transparent)]
struct Foobar<T> {
value: T,
}
impl<'de, T> serde::Deserialize<'de> for FoobarContainer<T>
where
T: serde::Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut v: Vec<Foobar<T>> = serde::Deserialize::deserialize(deserializer)?;
// I copied this from Stack Overflow without reading the surrounding
// text that describes why this is actually safe.
let values = unsafe {
let data = v.as_mut_ptr() as *mut T;
let len = v.len();
let cap = v.capacity();
std::mem::forget(v);
Vec::from_raw_parts(data, len, cap)
};
Ok(FoobarContainer { values })
}
}
See also:
How do I convert a Vec<T> to a Vec<U> without copying the vector?
Can I have a tuple as value in enums? Basically I want this in order to use an integer value as a database input and a string value as a friendly response to a UI caller.
For example:
#[derive(Deserialize, Debug)]
enum MyTestType {
A(0, "Default"),
B(1, "something else"),
C(18, "18"),
D(4, "D")
}
I am using serde crate in rust and it would be convenient to have it in order to avoid a struct here
Of course:
use serde::Serialize;
use serde_json;
#[derive(Serialize)]
enum Test {
A(u32, String), // NOT a tuple
B((u32, String)) // actual tuple
}
fn main () {
let a = Test::A(15, "Hello".to_string());
let b = Test::B((42, "Hi".to_string()));
println!("{}", serde_json::to_string(&a).unwrap());
println!("{}", serde_json::to_string(&b).unwrap())
}
Output:
{"A":[15,"Hello"]}
{"B":[42,"Hi"]}
I'm given a data-format that includes a sequence of objects with exactly one named field value each. Can I remove this layer of indirection while deserializing?
When deserializing, the natural representation would be
/// Each record has it's own `{ value: ... }` object
#[derive(serde::Deserialize)]
struct Foobar<T> {
value: T,
}
/// The naive representation, via `Foobar`...
#[derive(serde::Deserialize)]
struct FoobarContainer {
values: Vec<Foobar<T>>,
}
While Foobar adds no extra cost beyond T, I'd like to remove this layer of indirection at the type-level:
#[derive(serde::Deserialize)]
struct FoobarContainer {
values: Vec<T>,
}
Can Foobar be removed from FoobarContainer, while still using it using deserialization?
In the general case, there's no trivial way to make this transformation. For that, review these existing answers:
How do I write a Serde Visitor to convert an array of arrays of strings to a Vec<Vec<f64>>?
How to transform fields during deserialization using Serde?
The first is my normal go-to solution and looks like this in this example.
However, in your specific case, you say:
objects with exactly one named field value
And you've identified a key requirement:
While Foobar adds no extra cost beyond T
This means that you can make Foobar have a transparent representation and use unsafe Rust to transmute between the types (although not actually with mem::transmute):
struct FoobarContainer<T> {
values: Vec<T>,
}
#[derive(serde::Deserialize)]
#[repr(transparent)]
struct Foobar<T> {
value: T,
}
impl<'de, T> serde::Deserialize<'de> for FoobarContainer<T>
where
T: serde::Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut v: Vec<Foobar<T>> = serde::Deserialize::deserialize(deserializer)?;
// I copied this from Stack Overflow without reading the surrounding
// text that describes why this is actually safe.
let values = unsafe {
let data = v.as_mut_ptr() as *mut T;
let len = v.len();
let cap = v.capacity();
std::mem::forget(v);
Vec::from_raw_parts(data, len, cap)
};
Ok(FoobarContainer { values })
}
}
See also:
How do I convert a Vec<T> to a Vec<U> without copying the vector?
In Rust, tuple structs with only one field can be created like the following:
struct Centimeters(i32);
I want to do basic arithmetic with Centimeters without extracting their "inner" values every time with pattern matching, and without implementing the Add, Sub, ... traits and overloading operators.
What I want to do is:
let a = Centimeters(100);
let b = Centimeters(200);
assert_eq!(a + a, b);
is there a way to do it without extracting their "inner" values every time with pattern matching, and without implementing the Add, Sub, ... traits and overloading operators?
No, the only way is to implement the traits manually. Rust doesn't have an equivalent to the Haskell's GHC extension GeneralizedNewtypeDeriving which allows deriving on wrapper types to automatically implement any type class/trait that the wrapped type implements (and with the current set-up of Rust's #[derive] as a simple AST transformation, implementing it like Haskell is essentially impossible.)
To abbreviate the process, you could use a macro:
use std::ops::{Add, Sub};
macro_rules! obvious_impl {
(impl $trait_: ident for $type_: ident { fn $method: ident }) => {
impl $trait_<$type_> for $type_ {
type Output = $type_;
fn $method(self, $type_(b): $type_) -> $type_ {
let $type_(a) = self;
$type_(a.$method(&b))
}
}
}
}
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)]
pub struct Centimeters(i32);
obvious_impl! { impl Add for Centimeters { fn add } }
obvious_impl! { impl Sub for Centimeters { fn sub } }
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)]
pub struct Inches(i32);
obvious_impl! { impl Add for Inches { fn add } }
obvious_impl! { impl Sub for Inches { fn sub } }
fn main() {
let a = Centimeters(100);
let b = Centimeters(200);
let c = Inches(10);
let d = Inches(20);
println!("{:?} {:?}", a + b, c + d); // Centimeters(300) Inches(30)
// error:
// a + c;
}
playpen
I emulated the normal impl syntax in the macro to make it obvious what is happening just by looking at the macro invocation (i.e. reducing the need to look at the macro definition), and also to maintain Rust's natural searchability: if you're looking for traits on Centimeters just grep for for Centimeters and you'll find these macro invocations along with the normal impls.
If you are accessing the contents of the Centimeters type a lot, you could consider using a proper struct with a field to define the wrapper:
struct Centimeters { amt: i32 }
This allows you to write self.amt instead of having to do the pattern matching. You can also define a function like fn cm(x: i32) -> Centimeters { Centimeters { amt: x } }, called like cm(100), to avoid the verbosity of constructing a full struct.
You can also access the inner values of a tuple struct using the .0, .1 syntax.
I made the derive_more crate for this problem. It can derive lots of traits for structs of which the elements implement them.
You need to add derive_more to your Cargo.toml. Then you can write:
#[macro_use]
extern crate derive_more;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Add)]
struct Centimeters(i32);
fn main() {
let a = Centimeters(100);
let b = Centimeters(200);
assert_eq!(a + a, b);
}
For Rust version 1.10.0, it seems to me that type aliases would perfectly fit the situation you are describing. They simply give a type a different name.
Let's say all centimeters are u32s. Then I could just use the code
type Centimeters = u32;
Any trait that u32 has, Centimeters would automatically have. This doesn't eliminate the possibility of adding Centimeters to Inches. If you're careful, you wouldn't need different types.