2023-04-06 20:32:50 +00:00
/**
* @author brun0ne [brunonblok@gmail.com]
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs" ;
import OperationError from "../errors/OperationError.mjs" ;
/**
* PHP Serialize operation
*/
class PHPSerialize extends Operation {
/**
* PHPSerialize constructor
*/
constructor () {
super ();
this . name = "PHP Serialize" ;
this . module = "Default" ;
this . description = "Performs PHP serialization on JSON data.<br><br>This function does not support <code>object</code> tags.<br><br>Since PHP doesn't distinguish dicts and arrays, this operation is not always symmetric to <code>PHP Deserialize</code>.<br><br>Example:<br><code>[5,"abc",true]</code><br>becomes<br><code>a:3:{i:0;i:5;i:1;s:3:"abc";i:2;b:1;}<code>" ;
this . infoURL = "https://www.phpinternalsbook.com/php5/classes_objects/serialization.html" ;
this . inputType = "JSON" ;
this . outputType = "string" ;
this . args = [];
}
/**
* @param {JSON} input
* @param {Object[]} args
* @returns {string}
*/
run ( input , args ) {
/**
* Determines if a number is an integer
2023-04-06 21:03:46 +00:00
* @param {number} value
2023-04-06 20:32:50 +00:00
* @returns {boolean}
*/
function isInteger ( value ) {
return typeof value === "number" && parseInt ( value . toString (), 10 ) === value ;
}
/**
* Serialize basic types
2023-04-06 21:03:46 +00:00
* @param {string | number | boolean} content
2023-04-06 20:32:50 +00:00
* @returns {string}
*/
function serializeBasicTypes ( content ) {
const basicTypes = {
"string" : "s" ,
"integer" : "i" ,
"float" : "d" ,
"boolean" : "b"
};
/**
* Booleans
* cast to 0 or 1
*/
2023-04-06 21:03:46 +00:00
if ( typeof content === "boolean" ) {
return ` ${ basicTypes . boolean } : ${ content ? 1 : 0 } ` ;
2023-04-06 20:32:50 +00:00
}
2023-04-09 19:06:59 +00:00
/* Numbers */
2023-04-06 21:03:46 +00:00
if ( typeof content === "number" ) {
if ( isInteger ( content )) {
return ` ${ basicTypes . integer } : ${ content . toString () } ` ;
} else {
return ` ${ basicTypes . float } : ${ content . toString () } ` ;
2023-04-06 20:32:50 +00:00
}
}
2023-04-09 19:06:59 +00:00
/* Strings */
2023-04-06 20:32:50 +00:00
if ( typeof content === "string" )
2023-04-06 21:03:46 +00:00
return ` ${ basicTypes . string } : ${ content . length } :" ${ content } "` ;
2023-04-06 20:32:50 +00:00
/** This should be unreachable */
throw new OperationError ( `Encountered a non-implemented type: ${ typeof content } ` );
}
/**
* Recursively serialize
2023-04-06 21:03:46 +00:00
* @param {*} object
2023-04-06 20:32:50 +00:00
* @returns {string}
*/
function serialize ( object ) {
2023-04-09 19:06:59 +00:00
/* Null */
2023-04-06 20:32:50 +00:00
if ( object == null ) {
2023-04-06 21:03:46 +00:00
return `N;` ;
2023-04-06 20:32:50 +00:00
}
2023-04-06 21:03:46 +00:00
if ( typeof object !== "object" ) {
2023-04-09 19:06:59 +00:00
/* Basic types */
2023-04-06 20:32:50 +00:00
return ` ${ serializeBasicTypes ( object ) } ;` ;
2023-04-06 21:03:46 +00:00
} else if ( object instanceof Array ) {
2023-04-09 19:06:59 +00:00
/* Arrays */
2023-04-06 20:32:50 +00:00
const serializedElements = [];
2023-04-06 21:03:46 +00:00
2023-04-06 20:32:50 +00:00
for ( let i = 0 ; i < object . length ; i ++ ) {
serializedElements . push ( ` ${ serialize ( i ) }${ serialize ( object [ i ]) } ` );
}
2023-04-06 21:03:46 +00:00
return `a: ${ object . length } :{ ${ serializedElements . join ( "" ) } }` ;
} else if ( object instanceof Object ) {
/**
* Objects
* Note: the output cannot be guaranteed to be in the same order as the input
*/
2023-04-06 20:32:50 +00:00
const serializedElements = [];
const keys = Object . keys ( object );
2023-04-06 21:03:46 +00:00
2023-04-06 20:32:50 +00:00
for ( const key of keys ) {
serializedElements . push ( ` ${ serialize ( key ) }${ serialize ( object [ key ]) } ` );
}
2023-04-06 21:03:46 +00:00
return `a: ${ keys . length } :{ ${ serializedElements . join ( "" ) } }` ;
2023-04-06 20:32:50 +00:00
}
/** This should be unreachable */
throw new OperationError ( `Encountered a non-implemented type: ${ typeof object } ` );
}
return serialize ( input );
}
}
export default PHPSerialize ;