Previously, we blindly assume Ruby strings are UTF-8 and turn them
into Rust Strings (which *are* assumed to be UTF-8). This is clearly
unsafe so this commit adds some checks to cofirm that and generate
type errors appropiately.
Using the object (calling Rust methods from Ruby) after consuming
would raise a RuntimeError.
Also fixes some parser bugs that previously allowed invalid syntax
through in the arguments position.
The main use case for symbols is to use them as a HashMap key. However,
this introduces a GC problem – we cannot store Ruby values in the heap
without properly marking/registering them, otherwise they might get
GC'ed by Ruby unexpectedly. (In fact, this is already a problem if you
have a `Vec<VALUE>`.)
I tried to avoid introducing additional problems by pinning down any
symbols that goes thought the coercion protocol. This is probably
overly aggressive, as it would cause any dynamic symbols (e.g.
`String#to_sym`) to become un-GC-able. We can revisit this once we
have a more general-purpose system to encode pinning semantics in
the type system.
- Make `Checked` an associated type. This allows `from_ruby` to carry
over additional information (useful for `Option` etc)
- Move `ToRust` into `FromRuby` to ensure both get implemented together
This switches the `to_ruby` trait method to return a `Result`, which
allows the coercion to fail.
The most obvious use case for this is to implement coercion for the
`Result` type in Rust (included in this PR), but there could be other
reasons why a coercion might fail. For example, if we were to implement
a coercion between a Rust and Ruby regular expression, the coercion
could fail if the Rust regular expression uses some Rust-specific
features that are not supported by the Ruby regular expression
implementation.
Since we already have the `Cargo.toml`, we don't actually need the
user to pass the project name. Further more, the build task doesn't
actually work correctly if you pass any name _other than_ what is
in your `Cargo.toml` (as seen in #92).
Fixes#110.
This commit overhauls the macro, using a two-pass parse/codegen
approach that makes it easier for us to implement some long-desired
features. This commit adds support for multiple classes in a single
macro.