-
Couldn't load subscription status.
- Fork 8
Refactor native extension #4
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
Conversation
803b258 to
86b302e
Compare
| use ruru::result::Error as RuruError; | ||
|
|
||
| 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)RStringSymbolHashArray
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
AnyObjectto 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 transformationThe 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 objects are AnyObjects
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?
| use ruru::types::ValueType; | ||
| use inflector::cases::{camelcase, classcase, kebabcase, snakecase}; | ||
|
|
||
| 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. |
TransformandTryTransformtraitsmethods!macro