require "open3"
Configuration = Struct.new(:as, :variant, :name, :copy, :into) do
def initialize(as:, variant:, name: variant.downcase, copy: false, into: true)
super(as, variant, name, copy, into)
end
alias copy? copy
alias into? into
def render_as_method
bound = (copy? ? "val" : "ref val")
<<~RUST
/// Returns the value as a `Some(#{as_option_type})` if it is a `MetadataValue::#{variant}`, or `None` otherwise.
pub fn as_#{name}(&self) -> Option<#{as_option_type}> {
match *self {
Value::#{variant}(#{bound}) => Some(val),
_ => None,
}
}
RUST
end
def render_into_method
return "" unless into?
<<~RUST
/// Consumes `self` and returns the inner value as a `Some(#{as})` if it is a `MetadataValue::#{variant}`, or `None` otherwise.
pub fn into_#{name}(self) -> Option<#{as}> {
match self {
Value::#{variant}(val) => Some(val),
_ => None,
}
}
RUST
end
private
def as_option_type
if copy?
as
else
"&#{as}"
end
end
end
number_types = %w[u8 u16 u32 u64 i16 i32 i64 f64]
configurations = number_types.map { |name|
Configuration.new(as: name, variant: name.upcase, name: name, copy: true)
}
configurations += [
Configuration.new(as: "bool", variant: "Bool", copy: true),
Configuration.new(as: "String", variant: "String", name: "string"),
Configuration.new(as: "HashMap<String, Value>", variant: "Map"),
Configuration.new(as: "Vec<Value>", variant: "Array"),
Configuration.new(as: "str", variant: "String", name: "str", into: false),
]
code = <<RUST
// This file was generated by #{$0}.
impl Value {
RUST
configurations.each do |config|
code << config.render_as_method
end
configurations.each do |config|
code << config.render_into_method
end
code << "\n}"
stdout, stderr, status = Open3.capture3("rustfmt", stdin_data: code)
$stderr.puts stderr
if status.success?
File.write("src/metadata/value_conversions.rs", stdout)
else
$stderr.puts "\n\nFailed to rustfmt code."
exit 1
end