Last active
April 29, 2019 13:10
-
-
Save bew/38d8089cb5526f4e1f001e6e97db72e6 to your computer and use it in GitHub Desktop.
Rust's multi-type enum implementation in Crystal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# simplified example from rust: | |
# (https://github.com/srwalter/dbus-serialize/blob/b87fd9f78d9/src/types.rs) | |
# | |
# pub enum BasicValue { | |
# Byte(u8), | |
# Boolean(bool), | |
# Double(f64), | |
# Int16(i16), | |
# } | |
# | |
# pub enum Value { | |
# BasicValue(BasicValue), | |
# Array(Vec<Value>), | |
# } | |
# | |
# impl BasicValue { | |
# /// Returns the D-Bus type signature that corresponds to the Value | |
# pub fn get_signature(&self) -> &str { | |
# match self { | |
# &BasicValue::Byte(_) => "y", | |
# &BasicValue::Boolean(_) => "b", | |
# &BasicValue::Double(_) => "d", | |
# &BasicValue::Int16(_) => "n", | |
# } | |
# } | |
# } | |
# | |
# impl Value { | |
# /// Returns the D-Bus type signature that corresponds to the Value | |
# pub fn get_signature(&self) -> &str { | |
# match self { | |
# &Value::BasicValue(ref x) => x.get_signature(), | |
# &Value::Array(ref x) => "§", | |
# } | |
# } | |
# } | |
# Define some enum class (need another name..) | |
abstract struct DBus::BasicValue | |
record Byte < BasicValue, val : UInt8 | |
record Boolean < BasicValue, val : Bool | |
record Double < BasicValue, val : Float64 | |
record Int16 < BasicValue, val : ::Int16 | |
end | |
abstract struct DBus::Value | |
record BasicValue < Value, val : ::DBus::BasicValue | |
record Array < Value, val : ::Array(Value) | |
struct Array | |
# Helper constructor to create a Array(Value) from an Enumerable(::DBus::BasicValue) | |
def self.new(input : Enumerable(::DBus::BasicValue)) | |
dbus_array = ::Array(Value).new(input.size) | |
input.each do |dbus_val| | |
dbus_array << BasicValue.new(dbus_val) | |
end | |
new(dbus_array) | |
end | |
end | |
end | |
# Add impl | |
struct DBus::BasicValue | |
def get_signature : String | |
case self | |
when Byte | |
"y" | |
when Boolean | |
"b" | |
when Double | |
"d" | |
when Int16 | |
"n" | |
else raise "unreachable!" | |
end | |
end | |
end | |
struct DBus::Value | |
def get_signature : String | |
case self | |
when BasicValue # use in case statement! | |
self.val.get_signature | |
when Array | |
"(#{self.val.each.map(&.get_signature).join})" | |
else raise "unreachable!" | |
end | |
end | |
end | |
# Use! | |
bv_byte = DBus::BasicValue::Byte.new 42_u8 | |
bv_bool = DBus::BasicValue::Boolean.new true | |
bv_double = DBus::BasicValue::Double.new 42_f64 | |
bv_int16 = DBus::BasicValue::Int16.new 42_i16 | |
v_array = DBus::Value::Array.new({bv_byte, bv_bool, bv_double, bv_int16}) | |
pp! v_array, v_array.get_signature |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Live at https://carc.in/#/r/62rg 😃
btw, this kind of implementation was already done few years ago... 😬 crystal-lang/crystal#2787