@@ -7,6 +7,9 @@ import {ITypeDetector, IArbitraryObject} from "@wessberg/typedetector";
77 */
88export class Marshaller implements IMarshaller {
99 private static readonly SYMBOL_REGEX : RegExp = / S y m b o l \( ( [ ^ ) ] * ) \) / ;
10+ private static readonly FUNCTION_REGEX_1 : RegExp = / f u n c t i o n \s * \w * \s * \( [ ^ ) ] * \) \s * { / ;
11+ private static readonly FUNCTION_REGEX_2 : RegExp = / \( [ ^ ) ] * \) \s * = > / ;
12+ private static readonly FUNCTION_REGEX_3 : RegExp = / \w + \s * = > / ;
1013
1114 constructor ( private typeDetector : ITypeDetector ) { }
1215
@@ -34,6 +37,15 @@ export class Marshaller implements IMarshaller {
3437 return representation ;
3538 }
3639
40+ /**
41+ * Marshals a set into a function.
42+ * @param {Set<T> } data
43+ * @returns {Function }
44+ */
45+ private marshalSetToFunction < T > ( data : Set < T > ) : Function {
46+ return ( ) => data ;
47+ }
48+
3749 /**
3850 * Marshals a symbol into a string.
3951 * @param {symbol } data
@@ -45,6 +57,15 @@ export class Marshaller implements IMarshaller {
4557 return match [ 1 ] ;
4658 }
4759
60+ /**
61+ * Marshals a symbol into a function.
62+ * @param {symbol } data
63+ * @returns {Function }
64+ */
65+ private marshalSymbolToFunction ( data : symbol ) : Function {
66+ return ( ) => data ;
67+ }
68+
4869 /**
4970 * Marshals an object into a string.
5071 * @param {object } data
@@ -54,6 +75,15 @@ export class Marshaller implements IMarshaller {
5475 return JSON . stringify ( data ) ;
5576 }
5677
78+ /**
79+ * Marshals an object into a function.
80+ * @param {object } data
81+ * @returns {Function }
82+ */
83+ private marshalObjectToFunction < T > ( data : { [ key : string ] : T } ) : Function {
84+ return ( ) => data ;
85+ }
86+
5787 /**
5888 * Marshals a boolean into a string.
5989 * @param {boolean } data
@@ -63,6 +93,15 @@ export class Marshaller implements IMarshaller {
6393 return `${ data instanceof Boolean ? data . valueOf ( ) : data } ` ;
6494 }
6595
96+ /**
97+ * Marshals a boolean into a Function.
98+ * @param {boolean } data
99+ * @returns {Function }
100+ */
101+ private marshalBooleanToFunction ( data : boolean | Boolean ) : Function {
102+ return ( ) => data ;
103+ }
104+
66105 /**
67106 * Marshals a number into a string.
68107 * @param {number } data
@@ -72,6 +111,15 @@ export class Marshaller implements IMarshaller {
72111 return `${ data instanceof Number ? data . valueOf ( ) : data } ` ;
73112 }
74113
114+ /**
115+ * Marshals a number into a Function.
116+ * @param {number } data
117+ * @returns {Function }
118+ */
119+ private marshalNumberToFunction ( data : number | Number ) : Function {
120+ return ( ) => data ;
121+ }
122+
75123 /**
76124 * Marshals an array into a string.
77125 * @param {T[] } data
@@ -81,6 +129,36 @@ export class Marshaller implements IMarshaller {
81129 return JSON . stringify ( data ) ;
82130 }
83131
132+ /**
133+ * Marshals a function into a string.
134+ * @param {Function } data
135+ * @returns {string }
136+ */
137+ private marshalFunctionToString ( data : Function ) : string {
138+ return data . toString ( ) ;
139+ }
140+
141+ /**
142+ * Marshals an array into a Function.
143+ * @param {T[] } data
144+ * @returns {Function }
145+ */
146+ private marshalArrayToFunction < T > ( data : T [ ] ) : Function {
147+ return ( ) => data ;
148+ }
149+
150+ /**
151+ * Marshals a string into a Function.
152+ * @param {string } data
153+ * @returns {Function }
154+ */
155+ private marshalStringToFunction ( data : string ) : Function {
156+ if ( Marshaller . FUNCTION_REGEX_1 . test ( data ) ) return new Function ( `return ${ data } ` ) ( ) ;
157+ if ( Marshaller . FUNCTION_REGEX_2 . test ( data ) ) return new Function ( `return ${ data } ` ) ( ) ;
158+ if ( Marshaller . FUNCTION_REGEX_3 . test ( data ) ) return new Function ( `return ${ data } ` ) ( ) ;
159+ return ( ) => data ;
160+ }
161+
84162 /**
85163 * Marshals a string into a boolean.
86164 * @param {string } data
@@ -91,6 +169,15 @@ export class Marshaller implements IMarshaller {
91169 return primitive === "true" || primitive === "1" || primitive === "" ;
92170 }
93171
172+ /**
173+ * Marshals a Function into a boolean.
174+ * @param {Function } _
175+ * @returns {boolean }
176+ */
177+ private marshalFunctionToBoolean ( _ : Function ) : boolean {
178+ return true ;
179+ }
180+
94181 /**
95182 * Marshals a symbol into a boolean.
96183 * @param {symbol } data
@@ -164,6 +251,15 @@ export class Marshaller implements IMarshaller {
164251 return Symbol ( this . marshalNumberToString ( primitive ) ) ;
165252 }
166253
254+ /**
255+ * Marshals a number into a symbol.
256+ * @param {Function } data
257+ * @returns {symbol }
258+ */
259+ private marshalFunctionToSymbol ( data : Function ) : symbol {
260+ return Symbol ( this . marshalFunctionToString ( data ) ) ;
261+ }
262+
167263 /**
168264 * Marshals a set into a symbol.
169265 * @param {Set<T> } data
@@ -211,6 +307,15 @@ export class Marshaller implements IMarshaller {
211307 return Number . parseFloat ( primitive ) ;
212308 }
213309
310+ /**
311+ * Marshals a Function into a number.
312+ * @param {Function } _
313+ * @returns {number }
314+ */
315+ private marshalFunctionToNumber ( _ : Function ) : number {
316+ return 1 ;
317+ }
318+
214319 /**
215320 * Marshals a symbol into a number.
216321 * @param {symbol } data
@@ -270,14 +375,21 @@ export class Marshaller implements IMarshaller {
270375 }
271376
272377 /**
273- * Marshals a symbol into a boolean .
378+ * Marshals a symbol into a Set .
274379 * @param {symbol } data
275380 * @returns {Set<string> }
276381 */
277- private marshalSymbolToSet ( data : symbol ) : Set < string > {
278- const match = data . toString ( ) . match ( Marshaller . SYMBOL_REGEX ) ;
279- if ( match == null ) throw new ReferenceError ( `${ this . marshalSymbolToSet . name } was given an invalid symbol to marshal!` ) ;
280- return this . marshalStringToSet ( match [ 1 ] ) ;
382+ private marshalSymbolToSet ( data : symbol ) : Set < Symbol > {
383+ return new Set ( [ data ] ) ;
384+ }
385+
386+ /**
387+ * Marshals a Function into a Set.
388+ * @param {Function } data
389+ * @returns {Set<Function> }
390+ */
391+ private marshalFunctionToSet ( data : Function ) : Set < Function > {
392+ return new Set ( [ data ] ) ;
281393 }
282394
283395 /**
@@ -345,6 +457,15 @@ export class Marshaller implements IMarshaller {
345457 return this . marshalStringToArray ( match [ 1 ] ) ;
346458 }
347459
460+ /**
461+ * Marshals a Function into an array.
462+ * @param {Function } data
463+ * @returns {Function[] }
464+ */
465+ private marshalFunctionToArray ( data : Function ) : Function [ ] {
466+ return [ data ] ;
467+ }
468+
348469 /**
349470 * Marshals a set into an Array.
350471 * @param {Set<T> } data
@@ -421,6 +542,15 @@ export class Marshaller implements IMarshaller {
421542 }
422543 }
423544
545+ /**
546+ * Marshals a Function into an Object.
547+ * @param {Function } data
548+ * @returns {object }
549+ */
550+ private marshalFunctionToObject ( data : Function ) : { [ key : string ] : Function } {
551+ return { [ data . name ] : data } ;
552+ }
553+
424554 /**
425555 * Marshals a symbol into an object.
426556 * @param {symbol } data
@@ -471,6 +601,7 @@ export class Marshaller implements IMarshaller {
471601 */
472602 private marshalToBoolean < T > ( data : T ) : boolean | null {
473603 if ( this . typeDetector . isBoolean ( data ) ) return data ;
604+ if ( this . typeDetector . isFunction ( data ) ) return this . marshalFunctionToBoolean ( data ) ;
474605 if ( this . typeDetector . isString ( data ) ) return this . marshalStringToBoolean ( data ) ;
475606 if ( typeof data === "symbol" ) return this . marshalSymbolToBoolean ( data ) ;
476607 if ( data instanceof Set ) return this . marshalSetToBoolean ( data ) ;
@@ -487,6 +618,7 @@ export class Marshaller implements IMarshaller {
487618 */
488619 private marshalToNumber < T > ( data : T ) : number | null {
489620 if ( this . typeDetector . isNumber ( data ) ) return data ;
621+ if ( this . typeDetector . isFunction ( data ) ) return this . marshalFunctionToNumber ( data ) ;
490622 if ( this . typeDetector . isString ( data ) ) return this . marshalStringToNumber ( data ) ;
491623 if ( typeof data === "symbol" ) return this . marshalSymbolToNumber ( data ) ;
492624 if ( data instanceof Set ) return this . marshalSetToNumber ( data ) ;
@@ -503,6 +635,7 @@ export class Marshaller implements IMarshaller {
503635 */
504636 private marshalToSymbol < T > ( data : T ) : symbol | null {
505637 if ( typeof data === "symbol" ) return data ;
638+ if ( this . typeDetector . isFunction ( data ) ) return this . marshalFunctionToSymbol ( data ) ;
506639 if ( this . typeDetector . isString ( data ) ) return this . marshalStringToSymbol ( data ) ;
507640 if ( data instanceof Set ) return this . marshalSetToSymbol ( data ) ;
508641 if ( Array . isArray ( data ) ) return this . marshalArrayToSymbol ( data ) ;
@@ -520,6 +653,7 @@ export class Marshaller implements IMarshaller {
520653 */
521654 private marshalToString < T > ( data : T ) : string | null {
522655 if ( this . typeDetector . isString ( data ) ) return ( < String > data instanceof String ? < string > data . valueOf ( ) : data ) ;
656+ if ( this . typeDetector . isFunction ( data ) ) return this . marshalFunctionToString ( data ) ;
523657 if ( typeof data === "symbol" ) return this . marshalSymbolToString ( data ) ;
524658 if ( data instanceof Set ) return this . marshalSetToString ( data ) ;
525659 if ( Array . isArray ( data ) ) return this . marshalArrayToString ( data ) ;
@@ -530,6 +664,24 @@ export class Marshaller implements IMarshaller {
530664 return data . toString ( ) ;
531665 }
532666
667+ /**
668+ * Marshals the given data, whatever the type, into a Function.
669+ * @param {T } data
670+ * @returns {Function|null }
671+ */
672+ private marshalToFunction < T > ( data : T ) : Function | null {
673+ if ( this . typeDetector . isFunction ( data ) ) return data ;
674+ if ( this . typeDetector . isString ( data ) ) return this . marshalStringToFunction ( data ) ;
675+ if ( typeof data === "symbol" ) return this . marshalSymbolToFunction ( data ) ;
676+ if ( data instanceof Set ) return this . marshalSetToFunction ( data ) ;
677+ if ( Array . isArray ( data ) ) return this . marshalArrayToFunction ( data ) ;
678+ if ( this . typeDetector . isObject ( data ) ) return this . marshalObjectToFunction ( data ) ;
679+ if ( this . typeDetector . isBoolean ( data ) ) return this . marshalBooleanToFunction ( data ) ;
680+ if ( this . typeDetector . isNumber ( data ) ) return this . marshalNumberToFunction ( data ) ;
681+ if ( data == null ) return null ;
682+ return ( ) => data ;
683+ }
684+
533685 /**
534686 * Marshals the given data, whatever the type, into a Set.
535687 * @param {T } data
@@ -538,6 +690,7 @@ export class Marshaller implements IMarshaller {
538690 private marshalToSet < T > ( data : T ) : Set < { } > | null {
539691 if ( data instanceof Set ) return data ;
540692 if ( this . typeDetector . isString ( data ) ) return this . marshalStringToSet ( data ) ;
693+ if ( this . typeDetector . isFunction ( data ) ) return this . marshalFunctionToSet ( data ) ;
541694 if ( typeof data === "symbol" ) return this . marshalSymbolToSet ( data ) ;
542695 if ( Array . isArray ( data ) ) return this . marshalArrayToSet ( data ) ;
543696 if ( this . typeDetector . isObject ( data ) ) return this . marshalObjectToSet ( data ) ;
@@ -554,6 +707,7 @@ export class Marshaller implements IMarshaller {
554707 private marshalToArray < T > ( data : T ) : { } [ ] | null {
555708 if ( Array . isArray ( data ) ) return data ;
556709 if ( this . typeDetector . isString ( data ) ) return this . marshalStringToArray ( data ) ;
710+ if ( this . typeDetector . isFunction ( data ) ) return this . marshalFunctionToArray ( data ) ;
557711 if ( typeof data === "symbol" ) return this . marshalSymbolToArray ( data ) ;
558712 if ( data instanceof Set ) return this . marshalSetToArray ( data ) ;
559713 if ( this . typeDetector . isObject ( data ) ) return this . marshalObjectToArray ( data ) ;
@@ -569,6 +723,7 @@ export class Marshaller implements IMarshaller {
569723 */
570724 private marshalToObject < T > ( data : T ) : IArbitraryObject < { } > | null {
571725 if ( this . typeDetector . isObject ( data ) ) return data ;
726+ if ( this . typeDetector . isFunction ( data ) ) return this . marshalFunctionToObject ( data ) ;
572727 if ( Array . isArray ( data ) ) return this . marshalArrayToObject ( data ) ;
573728 if ( typeof data === "symbol" ) return this . marshalSymbolToObject ( data ) ;
574729 if ( this . typeDetector . isString ( data ) ) return this . marshalStringToObject ( data ) ;
@@ -638,6 +793,10 @@ export class Marshaller implements IMarshaller {
638793 if ( data === "NaN" ) return NaN ;
639794 if ( data === "Infinity" ) return Infinity ;
640795
796+ if ( Marshaller . FUNCTION_REGEX_1 . test ( primitive ) ) return new Function ( `return ${ primitive } ` ) ( ) ;
797+ if ( Marshaller . FUNCTION_REGEX_2 . test ( primitive ) ) return new Function ( `return ${ primitive } ` ) ( ) ;
798+ if ( Marshaller . FUNCTION_REGEX_3 . test ( primitive ) ) return new Function ( `return ${ primitive } ` ) ( ) ;
799+
641800 try {
642801 return JSON . parse ( primitive ) ;
643802 } catch ( e ) {
@@ -659,6 +818,7 @@ export class Marshaller implements IMarshaller {
659818 if ( this . typeDetector . isObject ( to ) || to === Object ) return this . marshalToObject ( data ) ;
660819 if ( this . typeDetector . isBoolean ( to ) || to === Boolean ) return this . marshalToBoolean ( data ) ;
661820 if ( this . typeDetector . isNumber ( to ) || to === Number ) return this . marshalToNumber ( data ) ;
821+ if ( this . typeDetector . isFunction ( to ) || to === < { } > Function ) return this . marshalToFunction ( data ) ;
662822 return this . marshalToString ( data ) ;
663823 }
664824
0 commit comments