Skip to content

Instantly share code, notes, and snippets.

@bew
Last active April 29, 2019 13:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bew/38d8089cb5526f4e1f001e6e97db72e6 to your computer and use it in GitHub Desktop.
Save bew/38d8089cb5526f4e1f001e6e97db72e6 to your computer and use it in GitHub Desktop.
Rust's multi-type enum implementation in Crystal
# 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
@bew
Copy link
Author

bew commented Jan 24, 2019

Live at https://carc.in/#/r/62rg 😃

btw, this kind of implementation was already done few years ago... 😬 crystal-lang/crystal#2787

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment