diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json
index ca762f1d..14cd881c 100755
--- a/src/core/config/Categories.json
+++ b/src/core/config/Categories.json
@@ -53,7 +53,8 @@
"To MessagePack",
"From MessagePack",
"To Braille",
- "From Braille"
+ "From Braille",
+ "To Python bytes"
]
},
{
diff --git a/src/core/operations/ToPythonBytes.mjs b/src/core/operations/ToPythonBytes.mjs
new file mode 100644
index 00000000..786bcf97
--- /dev/null
+++ b/src/core/operations/ToPythonBytes.mjs
@@ -0,0 +1,85 @@
+/**
+ * @author edouard hinard []
+ * @copyright Crown Copyright 2018
+ * @license Apache-2.0
+ */
+
+import Operation from "../Operation";
+import OperationError from "../errors/OperationError";
+
+/**
+ * To Python bytes operation
+ */
+class ToPythonBytes extends Operation {
+
+ /**
+ * ToPythonBytes constructor
+ */
+ constructor() {
+ super();
+
+ this.name = "To Python bytes";
+ this.module = "Default";
+ this.description = "Converts the input data to Python bytes literal.
e.g. The UTF-8 encoded string ça ma couté 20€
becomes b'\\xc3\\xa7a ma cout\\xc3\\xa9 20\\xe2\\x82\\xac'
";
+ this.infoURL = "https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals";
+ this.inputType = "ArrayBuffer" ;
+ this.outputType = "string";
+ this.args = [];
+ }
+
+ /**
+ * @param {ArrayBuffer} input
+ * @param {Object[]} args
+ * @returns {string}
+ */
+ run(input, args) {
+ let data = new Uint8Array(input);
+ if(!data) return "b''";
+
+ // First pass to decide which quote to use
+ // single quote is prefered
+ let onlySingleQuote = false;
+ for(let i = 0; i < data.length; i++) {
+ if(data[i] == 0x22) { // 0x22 <-> "
+ onlySingleQuote = false;
+ break;
+ }
+ if(data[i] == 0x27) { // 0x27 <-> '
+ onlySingleQuote = true;
+ }
+ }
+ let singleQuoted = true;
+ if(onlySingleQuote) {
+ singleQuoted = false;
+ }
+
+ // Second pass to convert byte array in Python bytes literal
+ let output = "";
+ for(let i = 0; i < data.length; i++) {
+ if(data[i] == 0x09) {
+ output += '\\t';
+ } else if(data[i] == 0x0a) {
+ output += '\\n';
+ } else if(data[i] == 0x0d) {
+ output += '\\r';
+ } else if(data[i] == 0x22 && !singleQuoted) {
+ output += '\\"';
+ } else if(data[i] == 0x27 && singleQuoted) {
+ output += "\\'";
+ } else if(data[i] == 0x5c) {
+ output += '\\';
+ } else if(data[i] < 0x20 || data[i] > 0x7e) {
+ output += '\\x' + data[i].toString(16).padStart(2,0);
+ } else {
+ output += String.fromCharCode(data[i]);
+ }
+ }
+ if(singleQuoted) {
+ return "b'" + output + "'";
+ } else {
+ return 'b"' + output + '"';
+ }
+ }
+}
+
+export default ToPythonBytes;