Hi.
Is it possible to make this code work without having FileExtension
be made up of tuples for SubtitleExtension
and VideoExtension
?
Play Ground
Hi.
Is it possible to make this code work without having FileExtension
be made up of tuples for SubtitleExtension
and VideoExtension
?
Play Ground
I see no FileExtension
enum and no tuples
In the code presented, it is not made up of tuples.
This is not considered two tuples?
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum FileExtension {
Subtitle(SubtitleExtension),
Video(VideoExtension),
}
A tuple in Rust is a type like (String, i32)
, or ()
, there’s also single-element tuples written e.g. as (Foo,)
.
There’s also “tuple-structs” which are structs that follow a tuple-like syntax. This is about the syntax of
and it is – crucially – syntax only that distinguishes tuple-structs from other structs. Tuple-structs don’t have field names, but the fields are identified by their order. You access them by index, e.g. foo.0
or by destructuring let Foo(x, y) = foo;
while ordinary structs use field names e.g. foo.bar
, or destructuring let Bar { number: x, flag: y } = bar;
.
E.g. a tuple struct definition can look like
struct Foo(i32, bool);
while an “ordinary” struct looks like
struct Bar {
number: i32,
flag: bool,
}
Finally, there’s enums, which have enum variants whose declaration mirrors struct definitions.
Enum variants are not types, so there are no tuple, and not even a tuple-struct in an enum like
enum Foo {
Variant(i32, bool),
AnotherVariant(float),
}
but Foo::Variant
and Foo::AnotherVariant
are … well I don’t actually know if there’s official terminology … but you could call them tuple-struct-style enum variants or something like that. Here’s an enum that also has a unit-struct-style variant and an ordinary-struct-style variant
enum Baz {
Variant(i32, bool),
UnitVariant,
AnotherVariant {
field: f32,
},
}
Enum fields are accessed by pattern matching; the difference between the different styles of variants is only syntax, too: Constructors and patterns look different, accordingly. E.g.
let baz1 = Bar::Variant(42, true);
let baz2 = Bar::UnitVariant;
let baz3 = Bar::AnotherVariant { field: 1.5 };
let baz4: Baz = …;
match baz4 {
Baz::Variant(x, y) => …,
Baz::UnitVariant => …,
Baz::AnotherVariant { field: z } => …,
}
P.S.: There’s actually one more difference beyond syntax: Calling the constructors of tuple-structs and tuple-struct-style enum variants doesn’t only look a lot like a function-call, these constructors can also be used as a function. E.g. for struct Foo(i32);
, you can then create a function pointer let foo_constructor: fn(i32) -> Foo = Foo;
or use the constructor Foo
where a closure is expected.
This may be off-topic, but I suggest
impl std::str::FromStr for FileExtension {
type Err = ExtensionError;
fn from_str(input: &str) -> Result<Self, Self::Err> {
let lowered = input.to_ascii_lowercase();
lowered.parse().map(FileExtension::Subtitle)
.or_else(|_| lowered.parse().map(FileExtension::Video) )
.map_err(|_| ExtensionError::Err(input.to_string()) )
}
}
To avoid duplication.
This looks good. I will give it a spin.
I was hoping to have a nicer implementation.
Thanks for this,. It worked really well.