How to use EnumAccess in Serde? - serialization

I am deserializing a externally coded enum for Avro. I have created an enum which matches it schema and I don't know how to take the variant identifer (a number) and choose the proper enum variant.
The target struct:
#[derive(Deserialize, Debug)]
struct UT {
timestamp: Timestamp,
metric: String,
}
#[derive(Deserialize, Debug)]
enum Timestamp {
Long(u64),
Int(i64),
Float(f32),
Double(f64)
}
When I get to deserialize_enum, I can read the variant id out of the stream but I don't know how to use it to choose the variant.
Dispatching to an enum variant is done by AvroEnumVisitor which implements both EnumAccess and VariantAccess. I can't get my code in VariantAccess to be called. EnumAccesss variant_seed is invoked by I don't know how to direct it, here's the nitty gritty:
// `EnumAccess` is provided to the `Visitor` to give it the ability to determine
// which variant of the enum is supposed to be deserialized.
//
// Note that all enum deserialization methods in Serde refer exclusively to the
// "externally tagged" enum representation.
impl<'de, 'a> EnumAccess<'de> for AvroEnumVisitor<'a, 'de> {
type Error = AvroError;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
where
V: serde::de::DeserializeSeed<'de>,
{
println!("EnumAccess::variant_seed");
// !!! This is the index in to the timestamp enum
let variant = self.de.visit_varint();
// !!! it's 1, corresponding to Int(i64)
// This is code I just copy/pasted
let val = match seed.deserialize(&mut *self.de) {
Ok(t) => t,
Err(e) => {
println!("error! {:#?}", e);
panic!("not sure how to direct deserialize");
}
};
Ok((val,self))
}
}
(playground)

Related

Kotlin enum like in the swift

I have enum in swift
enum Type {
case bool(Bool)
case int(Int)
case array([String])
}
Dont understand how i can convert this to kotlin code, i did like this:
enum class AnswerSheetType {
BOOL,
INT,
ARRAY
}
But how i can pass variable to enum type. For example then i want create method which will be return type with variable, like this(swift code):
func marks(for id: String) -> Type {
let answer = answers?[id]
if let boolAnswer = answer as? Bool {
return .bool(boolAnswer)
}
if let intAnswer = answer as? Int {
return .int(intAnswer)
}
if let arrayAnswer = answer as? [String] {
return .array(arrayAnswer)
}
}
You can use a sealed interface/class to represent this.
sealed interface Type {
data class BoolType(val value: Bool) : Type
data class IntType(val value: Int) : Type
data class ArrayType(val value: Array<String>) : Type
// if you have a case that doesn't have any associated values, just use an object
// object CaseWithoutAssociatedValues: Type
}
Usage:
// let someType: Type = .bool(true)
val someType: Type = Type.BoolType(true)
// just like how you can use a switch on a Swift enum, you can use a when like this too:
// This when is also exhaustive, if you specify all the implementers of Type
when (someType) {
is Type.BoolType -> println("Bool value: ${someType.value}")
is Type.IntType -> println("Int value: ${someType.value}")
is Type.ArrayType -> println("Array value: ${someType.value}")
}
Notice that in each of the branches, you can access someType.value, because of the smart-cast. This is unlike in Swift, where you would do pattern matching to get the associated values out.
As I was writing my answer Sweeper already answered with almost the identical solution. I wanted to add to that, that your marks function could then be written as this:
fun marks(id: String) : Type? {
when (val answer = answers?.get(id)) {
is Boolean -> return Type.BoolType(answer)
is Int -> return Type.IntType(answer)
is Array<*> -> if (answer.isArrayOf<String>()) return Type.ArrayType(answer as Array<String>)
}
return null
}
The Array case is a bit ugly but that is because checking on is Array<String> is not possible. The IDE will also still complain about having an unchecked cast but it should work. I don't know if there's a nicer way to handle this.

Best way to Strong-Type a primitive in Kotlin

Following similar patterns in other languages, I would be interested in producing the most useful way to strongly-type a primitive type in Kotlin.
The rationale, of course, is to have two types which are basically primitive (e.g. strings), but which cannot be assignable to each other by mistake.
My latest attempt is given here, and I'm interested to know how can it be minimized further (can defining the derived constructor be omitted?)
abstract class StronglyTyped<T>{
private var value: T
constructor(_value: T) {
value = _value
}
operator fun invoke(): T {
return value
}
}
class UserId: StronglyTyped<String> {
constructor(_value: String): super(_value) {}
}
class UserName: StronglyTyped<String> {
constructor(_value: String): super(_value) {}
}
fun main() {
val a = UserId("this is a userId")
val b = UserName("this is a userName")
var c: UserName
//c = a // <== won't compile
c = b
println(c())
}
Sounds like you're looking for value classes. More information is available in the official documentation.
An example might look something like the following:
value class Password(val value: String)
If you want to enforce some validation on the primitive, you can do so inside the init block.
value class UserId(val value: String) {
init {
require(value.length == 8) { "A userId must be exactly 8 characters long!" }
}
}
Note however, that this just provides compile-time type safety, because the original primitive types are used during the runtime.

Wrong number of lifetime parameters when using a modified `Chars` iterator

I want to implement the IntoIterator trait for a struct containing a String. The iterator is based on the chars() iterator, is supposed to count the '1' chars and accumulate the result. This is a simplified version of what I got so far:
use std::iter::Map;
use std::str::Chars;
fn main() {
let str_struct = StringStruct { system_string: String::from("1101") };
for a in str_struct {
println!("{}", a);
}
}
struct StringStruct {
system_string: String
}
impl IntoIterator for StringStruct {
type Item = u32;
type IntoIter = Map<Chars, Fn(char) -> u32>;
fn into_iter(self) -> Self::IntoIter {
let count = 0;
return self.system_string.chars().map(|c| match c {
Some('1') => {
count += 1;
return Some(count);
},
Some(chr) => return Some(count),
None => return None
});
}
}
Expected output: 1, 2, 2, 3
This fails with:
error[E0107]: wrong number of lifetime parameters: expected 1, found 0
--> src/main.rs:17:25
|
17 | type IntoIter = Map<Chars, Fn(char) -> u32>;
| ^^^^^ expected 1 lifetime parameter
The chars iterator should have the same lifetime as the StringStruct::system_string, but I have no idea how to express this or if this approach is viable at all.
To answer the question you asked, I'd recommend to impl IntoIterator for &StringStruct (a reference to a StringStruct instead of the struct directly). The code would look like this:
impl<'a> IntoIterator for &'a StringStruct {
type Item = u32;
type IntoIter = Map<Chars<'a>, Fn(char) -> u32>;
// ...
}
However, you will notice many more errors that have a different origin afterwards. The next error that pops up is that Fn(char) -> u32 does not have a constant size at compile time.
The problem is that you try to name the type of your closure by writing Fn(char) -> u32. But this is not the type of your closure, but merely a trait which is implemented by the closure. The type of a closure can't be named (sometimes called "Voldemort type").
This means that, right now, you can't specify the type of a Map<_, _> object. This is a known issue; the recently accepted impl Trait-RFC might offer a workaround for cases like this. But right now, it's not possible, sorry.
So how to solve it then? You need to create your own type that implements Iterator and use it instead of Map<_, _>. Note that you can still use the Chars iterator. Here is the full solution:
struct StringStructIter<'a> {
chars: Chars<'a>,
count: u32,
}
impl<'a> Iterator for StringStructIter<'a> {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
self.chars.next().map(|c| {
if c == '1' {
self.count += 1;
}
self.count
})
}
}
impl<'a> IntoIterator for &'a StringStruct {
type Item = u32;
type IntoIter = StringStructIter<'a>;
fn into_iter(self) -> Self::IntoIter {
StringStructIter {
chars: self.system_string.chars(),
count: 0,
}
}
}
fn main() {
let str_struct = StringStruct { system_string: String::from("1101") };
for a in &str_struct {
println!("{}", a);
}
}
And just a small note: an explicit return when not necessary is considered bad style in Rust. Better stick to rule and write idiomatic code by removing return whenever possible ;-)

Return an arbitrary Encodable from a match expression?

I have a match expression than can return several (builtin and custom) types, which will ultimately be serialized to JSON and returned from a web request. I would prefer to avoid repeating the serialization code or making a string copy in each match arm.
Each arm returns an Encodable; however, it seems that Encodable is not object-safe, so I cannot make a pointer to it.
Edit: Due to changes in Rust, the question has gone from "Is this a good way to do this?" to "How can I do this at all?" (This is with version rustc 1.0.0-nightly (ed530d7a3 2015-01-16 22:41:16 +0000))
extern crate "rustc-serialize" as rustc_serialize;
use rustc_serialize::{json, Encodable};
#[derive(RustcEncodable)]
struct Valid {
value: u32
}
#[derive(RustcEncodable)]
struct Error {
error: &'static str // '
}
fn main() {
let valid = true;
let result = match valid {
true => Box::new(Valid { value: 42 }) as Box<Encodable>,
false => Box::new(Error { error: "bork" }) as Box<Encodable>
};
let mut buf = String::new();
result.encode(&mut json::Encoder::new(&mut buf)).unwrap();
println!("{}", buf);
}
error: cannot convert to a trait object because trait `rustc-serialize::serialize::Encodable` is not object-safe [E0038]
There are 2 ways in which traits can be used in Rust:
As bounds in generic functions (static dispatch)
As trait objects, behind pointers (dynamic dispatch)
Because Encodable is not object-safe, we can't use dynamic dispatch, because the compiler doesn't allow us to create a pointer to an Encodable.
Therefore, we have to use static dispatch. To do this, I've moved the code that works on the Encodable to a new, generic function, and called it from each arm.
extern crate "rustc-serialize" as rustc_serialize;
use rustc_serialize::{json, Encodable};
#[derive(RustcEncodable)]
struct Valid {
value: u32
}
#[derive(RustcEncodable)]
struct Error {
error: &'static str // '
}
fn do_encode<E: Encodable>(e: E) -> () {
let mut buf = String::new();
e.encode(&mut json::Encoder::new(&mut buf)).unwrap();
println!("{}", buf);
}
fn main() {
let is_valid = true;
match is_valid {
true => do_encode(Valid { value: 42 }),
false => do_encode(Error { error: "bork" }),
};
}

typescript interface initialization

My level of typescript is 'ABSOLUTE BEGINNER' but I have a good OOP background. I am building an with typescript that reference an external t.ds library that contains the following interface:
interface ISimpleObject {
foo: string;
bar?: any;
}
Now, if I want to call a method that has an IRequestConfig parameter, how do I create one? I can see different options:
Create a simple implementation of ISimpleObject. I don't like this approach because it looks like boilerplate code to me
don't initialize the object (I fear this could break something...):
var x :IsimpleObject;
x.bar = 'xxx';
callMethod(x);
Cast a pojo:
var x :IsimpleObject = <IsimpleObject>{foo: 'yyy', bar:'xxx'};
I don't like this approach either because it doesn't enforce type safety...
I guess this is a fairly trivial question and I am missing something trivial about typescript.
Typescript2:
const simpleObject = {} as ISimpleObject;
If you have an interface like:
interface ISimpleObject {
foo: string;
bar?: any;
}
This interface is only used at compile time and for code-hinting/intellisense. Interfaces are used to provide a rigorous and type-safe way of using an object with a defined signature in a consistent manner.
If you have a function using the interface defined above:
function start(config: ISimpleObject):void {
}
The TypeScript compile will fail if an object does not have the exact signature of the ISimpleObject interface.
There are multiple valid techniques for calling the function start:
// matches the interface as there is a foo property
start({foo: 'hello'});
// Type assertion -- intellisense will "know" that this is an ISimpleObject
// but it's not necessary as shown above to assert the type
var x = <ISimpleObject> { foo: 'hello' };
start(x);
// the type was inferred by declaration of variable type
var x : ISimpleObject = { foo: 'hello' };
start(x);
// the signature matches ... intellisense won't treat the variable x
// as anything but an object with a property of foo.
var x = { foo: 'hello' };
start(x);
// and a class option:
class Simple implements ISimpleObject {
constructor (public foo: string, public bar?: any) {
// automatically creates properties for foo and bar
}
}
start(new Simple("hello"));
Any time the signature doesn't match, the compile will fail:
// compile fail
var bad = { foobar: 'bad' };
start( bad );
// compile fail
var bad: ISimpleObject = { foobar: 'bad' };
// and so on.
There is no "right" way to do it. It's a matter of style choice. If it were an object that was constructed (rather than just directly passed as a parameter), I'd normally declare the type:
var config: ISimpleObject = { foo: 'hello' };
That way code-completion/IntelliSense will work anywhere I used the config variable:
config.bar = { extra: '2014' };
There is no "casting" in TypeScript. It is called a type assertion and shouldn't be needed in the cases described here (I included an example above where it could be used). There's no need to declare the variable Type and then use an assertion in this case (as the type was already known).
You can't create an instance of an interface since Typescript doesn't "translate" it into js. You can check the js that is created and you will see nothing in it. It's simple for compile errors, type safety and intelisense.
interface IStackOverFlow
{
prop1 : string;
prop2 : number;
}
public MyFunc(obj : IStackOverFlow)
{
// do stuff
}
var obj = {prop1: 'str', prop2: 3};
MyFunc(obj); // ok
var obj2 = {prop1: 'str'};
MyFunc(obj); // error, you are missing prop2
// getObj returns a "any" type but you can cast it to IStackOverFlow.
// This is just an example.
var obj = <IStackOverFlow> getObj();