|
2 | 2 | extern crate ruru;
|
3 | 3 | extern crate inflector;
|
4 | 4 |
|
5 |
| -// // dash: kebab-case |
6 |
| -use inflector::cases::kebabcase::to_kebab_case; |
7 |
| -// // underscore: snake_case |
8 |
| -use inflector::cases::snakecase::to_snake_case; |
9 |
| -// // camel_lower: camelCase |
10 |
| -use inflector::cases::camelcase::to_camel_case; |
11 |
| -// // camel: ClassCase (PascalCase) |
12 |
| -use inflector::cases::classcase::to_class_case; |
13 |
| - |
14 |
| -use ruru::{Class, Object, RString, Hash, Array, Symbol, AnyObject, VM}; |
15 |
| -use ruru::types::ValueType; |
| 5 | +use inflector::cases::{camelcase, classcase, kebabcase, snakecase}; |
16 | 6 |
|
17 |
| -class!(CaseTransform); |
| 7 | +use ruru::{Class, Object, VerifiedObject, RString, Hash, Array, Symbol, AnyObject}; |
| 8 | +use ruru::types::ValueType; |
| 9 | +use ruru::result::Error as RuruError; |
18 | 10 |
|
19 |
| -methods! ( |
20 |
| - CaseTransform, |
21 |
| - itself, |
| 11 | +trait Transform: Object { |
| 12 | + fn transform(&self, transform_function: &Fn(String) -> String) -> AnyObject; |
| 13 | +} |
22 | 14 |
|
23 |
| - fn deepTransformKeys(hash: Hash, block: &Fn(String) -> String) -> Hash { |
24 |
| - let result = Hash::new(); |
| 15 | +impl Transform for AnyObject { |
| 16 | + fn transform(&self, _transform_function: &Fn(String) -> String) -> AnyObject { |
| 17 | + self.clone() |
| 18 | + } |
| 19 | +} |
25 | 20 |
|
26 |
| - hash.unwrap().each(|key, value| { |
27 |
| - let newValue = if value.ty() == ValueType::Hash { deepTransformKeys(value, block).to_any_object() } else { value }; |
28 |
| - let newKey = RString::new(block(key.unwrap().to_string())); |
29 |
| - result.store(newKey, newValue); |
30 |
| - }); |
| 21 | +impl Transform for RString { |
| 22 | + fn transform(&self, transform_function: &Fn(String) -> String) -> AnyObject { |
| 23 | + let result = transform_function(self.to_string(); |
31 | 24 |
|
32 |
| - result |
| 25 | + RString::new(&result)).to_any_object() |
33 | 26 | }
|
| 27 | +} |
| 28 | + |
| 29 | +impl Transform for Symbol { |
| 30 | + fn transform(&self, transform_function: &Fn(String) -> String) -> AnyObject { |
| 31 | + let result = transform_function(self.to_string()); |
34 | 32 |
|
35 |
| - fn transformArray(value: Array, transformMethod: &Fn(AnyObject) -> AnyObject) -> Array { |
36 |
| - value.map(|item| transformMethod(item)).unwrap() |
| 33 | + Symbol::new(&result).to_any_object() |
37 | 34 | }
|
| 35 | +} |
| 36 | + |
| 37 | +impl Transform for Hash { |
| 38 | + fn transform(&self, transform_function: &Fn(String) -> String) -> AnyObject { |
| 39 | + let mut result = Hash::new(); |
| 40 | + |
| 41 | + self.each(|key, value| { |
| 42 | + let new_key = transform(key, transform_function); |
| 43 | + let new_value = match value.ty() { |
| 44 | + ValueType::Hash => transform(value, transform_function), |
| 45 | + _ => value, |
| 46 | + }; |
38 | 47 |
|
39 |
| - fn transformHash(value: Hash, transformMethod: &Fn(AnyObject) -> AnyObject) -> Hash { |
40 |
| - deepTransformKeys(value, |key| transformMethod(key)) |
| 48 | + result.store(new_key, new_value); |
| 49 | + }); |
| 50 | + |
| 51 | + result.to_any_object() |
41 | 52 | }
|
| 53 | +} |
| 54 | + |
| 55 | +impl Transform for Array { |
| 56 | + fn transform(&self, transform_function: &Fn(String) -> String) -> AnyObject { |
| 57 | + // Temp hack to consume &self for iterator |
| 58 | + let result = unsafe { self.to_any_object().to::<Array>() }; |
42 | 59 |
|
43 |
| - fn transformSymbol(value: Symbol, transformMethod: &Fn(AnyObject) -> AnyObject) -> Symbol { |
44 |
| - let transformed = transformMethod(value); |
45 |
| - Symbol::new(transformed); |
| 60 | + result.into_iter() |
| 61 | + .map(|item| transform(item, transform_function)) |
| 62 | + .collect::<Array>() |
| 63 | + .to_any_object() |
46 | 64 | }
|
| 65 | +} |
47 | 66 |
|
48 |
| - fn transform( |
49 |
| - value: AnyObject, |
50 |
| - objectTransform: &Fn(AnyObject) -> AnyObject, |
51 |
| - keyTransform: &Fn(String) -> String |
52 |
| - ) -> AnyObject { |
53 |
| - match value.unwrap().ty() { |
54 |
| - ValueType::Array => transformArray(value, objectTransform).to_any_object(), |
55 |
| - ValueType::Hash => transformHash(value, objectTransform).to_any_object(), |
56 |
| - ValueType::Symbol => transformSymbol(value, objectTransform).to_any_object(), |
57 |
| - ValueType::RString => keyTransform(value).to_any_object(), |
58 |
| - ValueType::Object => value |
59 |
| - } |
| 67 | +trait TryTransform: Object { |
| 68 | + fn try_transform<T>(&self, |
| 69 | + transform_function: &Fn(String) -> String) |
| 70 | + -> Result<AnyObject, RuruError> |
| 71 | + where T: VerifiedObject + Transform |
| 72 | + { |
| 73 | + self.try_convert_to::<T>().map(|object| object.transform(transform_function)) |
60 | 74 | }
|
| 75 | +} |
| 76 | + |
| 77 | +impl TryTransform for AnyObject {} |
| 78 | + |
| 79 | +fn transform(object: AnyObject, key_transform: &Fn(String) -> String) -> AnyObject { |
| 80 | + let result = object.try_transform::<RString>(key_transform) |
| 81 | + .or_else(|_| object.try_transform::<Symbol>(key_transform)) |
| 82 | + .or_else(|_| object.try_transform::<Array>(key_transform)) |
| 83 | + .or_else(|_| object.try_transform::<Hash>(key_transform)) |
| 84 | + .or_else(|_| object.try_transform::<AnyObject>(key_transform)); |
| 85 | + |
| 86 | + result.unwrap() |
| 87 | +} |
| 88 | + |
| 89 | +fn to_pascal_case(key: String) -> String { |
| 90 | + classcase::to_class_case(snakecase::to_snake_case(key)) |
| 91 | +} |
| 92 | + |
| 93 | +fn to_camel_case(key: String) -> String { |
| 94 | + camelcase::to_camel_case(snakecase::to_snake_case(key)) |
| 95 | +} |
| 96 | + |
| 97 | +fn to_dashed_case(key: String) -> String { |
| 98 | + kebabcase::to_kebab_case(snakecase::to_snake_case(key)) |
| 99 | +} |
| 100 | + |
| 101 | +fn to_snake_case(key: String) -> String { |
| 102 | + snakecase::to_snake_case(key) |
| 103 | +} |
61 | 104 |
|
62 |
| - fn toPascalCase(key: String) -> String { to_class_case(to_snake_case(key.unwrap())) } |
63 |
| - fn toCamelCase(key: String) -> String { to_camel_case(to_snake_case(key.unwrap())) } |
64 |
| - fn toDashedCase(key: String) -> String { to_kebab_case(to_snake_case(key.unwrap())) } |
65 |
| - fn toSnakeCase(key: String) -> String { to_snake_case(key.unwrap()) } |
| 105 | +class!(CaseTransform); |
| 106 | + |
| 107 | +methods! ( |
| 108 | + CaseTransform, |
| 109 | + _itself, |
66 | 110 |
|
67 |
| - fn camel(value: AnyObject) -> AnyObject { transform(value.unwrap().to_any_object(), &camel, &toPascalCase) } |
68 |
| - fn camelLower(value: AnyObject) -> AnyObject { transform(value.unwrap().to_any_object(), &camelLower, &toCamelCase) } |
69 |
| - fn dash(value: AnyObject) -> AnyObject { transform(value.unwrap().to_any_object(), &dash, &toDashedCase) } |
70 |
| - fn underscore(value: AnyObject) -> AnyObject { transform(value.unwrap(), &underscore, &toSnakeCase) } |
71 |
| - fn unaltered(value: AnyObject) -> AnyObject { value.unwrap().to_any_object() } |
| 111 | + fn camel(object: AnyObject) -> AnyObject { transform(value.unwrap(), &to_pascal_case) } |
| 112 | + fn camel_lower(object: AnyObject) -> AnyObject { transform(object.unwrap(), &to_camel_case) } |
| 113 | + fn dash(object: AnyObject) -> AnyObject { transform(object.unwrap(), &to_dashed_case) } |
| 114 | + fn underscore(object: AnyObject) -> AnyObject { transform(object.unwrap(), &to_snake_case) } |
| 115 | + fn unaltered(object: AnyObject) -> AnyObject { object.unwrap() } |
72 | 116 | );
|
73 | 117 |
|
74 | 118 | #[no_mangle]
|
75 |
| -pub extern fn initialize_case_transform() { |
76 |
| - Class::new("CaseTransform", None).define(|itself| { |
| 119 | +pub extern "C" fn initialize_case_transform() { |
| 120 | + Class::from_existing("CaseTransform").define(|itself| { |
77 | 121 | itself.def_self("camel", camel);
|
78 |
| - itself.def_self("camel_lower", camelLower); |
| 122 | + itself.def_self("camel_lower", camel_lower); |
79 | 123 | itself.def_self("dash", dash);
|
80 | 124 | itself.def_self("underscore", underscore);
|
81 | 125 | itself.def_self("unaltered", unaltered);
|
|
0 commit comments