Define Enum as a Struct (why use this syntax) - struct

In Rust's chrono library there is this code in src/format/mod.rs#L338-L345:
pub struct ParseError(ParseErrorKind);
enum ParseErrorKind {
OutOfRange,
...
}
In the first line, what does the syntax struct ParseError(ParseErrorKind) mean? Is enum ParseErrorKind somewhat "aliased" as a struct called ParseError, or is ParseError a struct that contains an anonymous field of enum type ParseErrorKind? If the latter, how would one access the field? Or is this something else?
What is the advantage of using this struct syntax? Why not use ParseErrorKind as a type directly (instead of wrapping it into a struct)?

In the first line, what does the syntax struct ParseError(ParseErrorKind) mean? Is enum ParseErrorKind somewhat "aliased" as a struct called ParseError, or is ParseError a struct that contains an anonymous field of enum type ParseErrorKind? If the latter, how would one access the field? Or is this something else?
It is a tuple struct, which in this case wraps an inner error type.
The main difference from other structs is that fields are not named. Instead they are accessed like tuples (ex my_instace.0, to refer to the inner data).
Refer to the docs for more info
What is the advantage of using this struct syntax? Why not use ParseErrorKind as a type directly (instead of wrapping it into a struct)?
In this case it abstract the enum constructors over a single type. My guess is that they decided that the error kind is an implementation detail and should not be exposed in the API. Notice that ParseErrorKind is private while ParseError is public (with private access to the single tuple inside).
Additionally, it is also a common pattern to wrap types in order to expand what those types can do if those types are not native to your own crate.

Related

Dealing with `Options` and defaults when parsing in TOML structs with Rust+Serde

I have been working on configuration parsing code and wondered if you could help me to pick the best types for this code.
I am trying to parse the following TOML:
[default]
a=10
b="abc"
[section1]
a = 78
[section2]
b="xyz"
The types of keys are the same in each section and each field follows the chain of defaults: sectionX.value => default.value => default value hardcoded in Rust via x.value.or(default.value).or(Some(...) for each field.
The most straightforward way to declare it in Rust (including serde attributes)
struct Section{
a: Option<usize>,
b: Option<String>,
}
The problem is that I want to parse all defaults first, and then use a fully materialized struct with no unassigned values in my code.
struct Section{
a: usize,
b: String,
}
I can use the following approaches:
Use original Section struct and always to unwrap/expect because I "know" the defaults have been assigned in the config parsing code. I make a mistake, I can catch panic and that does not look tidy. I'd like to leverage more help from the compiler.
Use the second Section struct (the one that has no Options). I can assign defaults via Serde annotations, but then I am loosing the signal that something was unspecified and needs a default from another level.
Declare both variants of the struct. This is the most verbose variant and I will look even more verbose when I grow 20+ fields or embedded structs in the config.
Generated Solution 3 via macros or some clever typing. Is there a crate for this? Maybe Section could have some generic type that can be Option in one place, but then "newtype" wrapper with a single value somewhere else?
Something else?
Some of the solutions above would work alright, but maybe there is a known elegant solution.

Rust tonic and prost_types conversion

I'm using tonic framework, a rust grpc server implementation. In the generated rust code from the proto file, I have a struct which has a field:
#[prost(message, optional, tag="3")]
pub data: ::core::option::Option<::prost_types::Value>,
generated from a protobuff field:
google.protobuf.Value data = 3;
I can't seem to find a way to init data which is type prost_types::Value by converting a struct I have. I'm doing something like:
prost_types::Value::try_from(myOwnsStructVar)
But it does not work. Anyone have used prost_types lib before and know how to encode/convert to prost_types::Value
myOwnsStructVar is a type struct. I need to convert it to prost_types::Struct So then I can do:
prost_types::value::Kind::StructValue(myOwnsStructVarAfterConversiontToProstStruct)
Just from looking at the docs, we can see that Value is a struct with a single public field kind which is of type Option<Kind>. The docs say that if this field is None then that indicates an error. If you look at the docs for Kind, then it's apparent this is where the actual data is stored. So if you want to initialize something of type Value then you'd want to do something like the following, substituting in the appropriate variant of Kind for your use case:
Value {
kind: Some(Kind::NumberValue(10.0f64))
}
The reason that your try_from solution didn't work is because there are no TryFrom implementations for Value other than the default blanket implementation.

Is it possible to change/generate code through derive macro inside of the struct that uses that macro?

I was curious whether it is possible to change the code inside the struct that uses derive macro, or are you only limited to generating the new code outside?
Example
Adding another field to the Building struct through SomeMacro.
#[derive(SomeMacro)]
pub struct Building {
colour: String,
// Add height: u8 through derive macro
}
It is not possible. This is a fundamental characteristic of derive macros: they take an existing item's tokens and generate new, separate items (usually trait impls).
If you want to modify the struct item itself, you must instead make an attribute macro, which can return a replacement for the input tokens. Attribute macros aren't invoked using the derive attribute but are attributes themselves: #[some_macro] pub struct Building { ...

How do I call a getter from another Substrate module?

I have two modules, MyCore and Special. MyCore has a public getter:
pub fn get_core_account() -> Option<T::AccountId>
Which gets an accountId. If I call this from Special in a simple manner:
let core_account = MyCore::get_core_account();
then rustc complains that it can't infer the type, which is odd because the public setters don't need further info. So I make the type explicit
let core_account: Option<T::AccountId> = MyCore::get_core_account();
But this triggers demands for type specifiers on the call, so we elaborate:
let core_account: Option<T::AccountId> = MyCore::<T>::get_core_account();
At which point rust complains that it can't find get_core_account, because Special doesn't have a restriction to implement MyCore::Trait. But I don't want Special to implement MyCore::Trait! I want to call a getter!
Perhaps I'm missing something regarding the use of T here - in theory, Special is a trait templated over some T, which we can implement using a Test class if we implement the required types.
Does Special really need to implement MyCore::Trait?
What you want to do is possible, yet you are probably doing something wrong which is not clearly demonstrated in the question. Would be very helpful if you post the Trait definitions of both modules.
Does Special really need to implement MyCore::Trait?
No. You might have to make it a trait bound though.
Basically, you have two options in such cases:
If your Core is something that all other modules will depend on, similar to frame-system, you can explicitly depend on it. Note that this path should be taken with care and you don't want to create too big of a monolithic software with this mindset. Nonetheless, in that case, you can just do:
// in special.rs
// This is needed because then we can pass `T` into `mycore::Module<_>`.
pub trait Trait: mucore::Trait {
...
}
// and then later on you can call:
<mycore::Module<T>>:: get_core_account()
This seems like the approach that you wanted to take.
Alternatively, you can bind the two modules together without this explicit dependency. This is useful for when you want your Special to receive the getter eventually, but you don't really care who provides it. Or in other words, if multiple candidates can provide this getter and you want to be generic over it.
For this, you first need a common trait definition.
// in some common dependency
trait CoreGetterProvider<AccountId> {
fn getter() -> Option<AccountId>;
}
and your Special would express:
pub trait Trait {
// .. other stuff. Assuming that it has a common AccountId with Core.
type Getter: CoreGetterProvider<Self::AccountId>
}
And your Core implements it
// in Core.rs
impl<T: Trait> CoreGetterProvider<T::AccountId> for Module<T> { ... }
Finally, when building the runtime, you can pass the Core module to Special.
impl core::Trait for Runtime { ... }
impl special::Trait for Runtime {
type Getter = core::Module<Runtime> // or just `Core`. construct_runtime! creates this type alias.
}

What is the difference between using a type as a different name and a type alias?

What is the difference between
use hyper::status::StatusCode as Error;
and
type Error = hyper::status::StatusCode;
Are the any more differences between them except that type can be also pub type? What are the benefits between using one or another?
In case of simple types, like in your example, there doesn't seem to be any semantic difference. Moreover, there is a direct analogue with use to pub type, it's pub use:
// will be available to other modules
pub use hyper::status::StatusCode as Error;
However, there are differences in more complex cases. For example, you can define generic type aliases or aliases for specialized generic types:
type Result<T> = ::std::result::Result<T, MyError>;
type OptionI32 = Option<i32>;
The general idea is that you usually use type aliases because they are more powerful and suggest the intent more clearly, like with Result, and you use use .. as .. when you only want to import that specific name but it conflicts with something which is already in the current namespace:
use std::io::Read as StdRead;
trait Read: StdRead { ... }
Note that using path-qualified identifiers should be preferred to use renaming. The above is better written as
use std::io;
trait Read: io::Read { ... }
(unless Read methods are used for some concrete type in the same file, of course).
Using use .. as .. as a substitute for type (in case where it is possible) is uncommon and I think it should be avoided.

Resources