-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor native extension #4
Refactor native extension #4
Conversation
803b258
to
86b302e
Compare
|
||
class!(CaseTransform); | ||
trait Transform: Object { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Transform
describes an interface for transformation. It can be implemented only to Ruby objects due to Object
constraint.
Then we make type-specific implementations for
AnyObject
(no-op)RString
Symbol
Hash
Array
by implementing transorm
methods.
fn transformSymbol(value: Symbol, transformMethod: &Fn(AnyObject) -> AnyObject) -> Symbol { | ||
let transformed = transformMethod(value); | ||
Symbol::new(transformed); | ||
trait TryTransform: Object { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TryTransform
trait itself is needed only to define try_transform
method on AnyObject
. Rust does not allow to change the implementation of types that is not owned by current crate.
let transformed = transformMethod(value); | ||
Symbol::new(transformed); | ||
trait TryTransform: Object { | ||
fn try_transform<T>(&self, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try_transform<T>
method:
- Tries to convert current
AnyObject
to the typeT
. - :
- If the conversion is successful it performs a transformation.
- otherwise, returns an error from
try_convert_to
.
An example of usage of try_transform
is
object.try_transform::<Hash>(key_transform) // if the object is a hash, try to do a hash transformation
The interesting part here is the constraints for T
type: where T: VerifiedObject + Transform
.
ValueType::Object => value | ||
} | ||
fn transform(object: AnyObject, key_transform: &Fn(String) -> String) -> AnyObject { | ||
let result = object.try_transform::<RString>(key_transform) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try to transform the object as a RString
Otherwise try to transform the object as a Symbol
...
Otherwise try to transform the object as a AnyObject
(it is any unkown class, do nothing)
fn toCamelCase(key: String) -> String { to_camel_case(to_snake_case(key.unwrap())) } | ||
fn toDashedCase(key: String) -> String { to_kebab_case(to_snake_case(key.unwrap())) } | ||
fn toSnakeCase(key: String) -> String { to_snake_case(key.unwrap()) } | ||
result.unwrap() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can safely unwrap here, because result
has AnyObject
type
- Add `Transform` and `TryTransform` traits - Move Rust functions outside `methods!` macro - Change naming to match conventions
86b302e
to
f7dc641
Compare
fn dash(value: AnyObject) -> AnyObject { transform(value.unwrap().to_any_object(), &dash, &toDashedCase) } | ||
fn underscore(value: AnyObject) -> AnyObject { transform(value.unwrap(), &underscore, &toSnakeCase) } | ||
fn unaltered(value: AnyObject) -> AnyObject { value.unwrap().to_any_object() } | ||
fn camel(object: AnyObject) -> AnyObject { transform(value.unwrap(), &to_pascal_case) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And we can safely unwrap in this methods, because object
s are AnyObject
s
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
legit
fn toSnakeCase(key: String) -> String { to_snake_case(key.unwrap()) } | ||
class!(CaseTransform); | ||
|
||
methods! ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All the functions which are not used directly in the CaseTransform
class are moved outside methods!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this makes sense!
That's what I meant in d-unsed/ruru#35 :) I hope it helps!
|
|
||
use ruru::{Class, Object, RString, Hash, Array, Symbol, AnyObject, VM}; | ||
use ruru::types::ValueType; | ||
use inflector::cases::{camelcase, classcase, kebabcase, snakecase}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is handy!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a way to import the methods into the 'global' namespace of the file? so you don't have to do classcase::to_class_case
?
|
||
class!(CaseTransform); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why was this removed? I saw it one one of the example repos, though I don't know what its purpose was
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The line was moved to the bottom of the file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
methods! ( | ||
CaseTransform, | ||
itself, | ||
trait Transform: Object { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to read up on traits and impls
for myself:
- https://doc.rust-lang.org/book/traits.html
- https://doc.rust-lang.org/book/generics.html looks like impl's are just implementations of a generic struct?
fn transformSymbol(value: Symbol, transformMethod: &Fn(AnyObject) -> AnyObject) -> Symbol { | ||
let transformed = transformMethod(value); | ||
Symbol::new(transformed); | ||
result.into_iter() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
arrays are iterable by default?
edit: not*
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They kinda are iterable, but after explicit conversion to iterators :) Same for slices, vectors etc
fn toCamelCase(key: String) -> String { to_camel_case(to_snake_case(key.unwrap())) } | ||
fn toDashedCase(key: String) -> String { to_kebab_case(to_snake_case(key.unwrap())) } | ||
fn toSnakeCase(key: String) -> String { to_snake_case(key.unwrap()) } | ||
class!(CaseTransform); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here it is!
@d-unseductable this helps a ton! thanks so much! |
I have to wait till I get to my personal laptop to try this out, so I have consistent hardware for my benchmarking :-) |
You're welcome! Please let me know when you get the results |
Just for some background here is the comparison between pure ruby, and my last successful compile: rails-api/active_model_serializers#1928 (comment) It actually significantly hurt performance. haha. |
rails-api/active_model_serializers#1928 (comment) So, slightly faster... but still am not sure what the deal is with the slowness. Still, I appreciate you teaching me rust! |
I guess what could be next is seeing if fiddle is slowing me down. |
Transform
andTryTransform
traitsmethods!
macro