|
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