|  | 
| 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