[gjs: 2/3] GLib: add shortcut for bytestring GVariant



commit e59888dcd7215852c01b2da1f05f4fcab6f3d069
Author: Philip Chimento <philip endlessm com>
Date:   Thu Sep 13 15:51:16 2018 -0700

    GLib: add shortcut for bytestring GVariant
    
    GVariant has two semantically different uses for variants of the 'ay'
    type: array of bytes, and bytestring (encoded string data.) Arrays of
    bytes can contain anything, including embedded 0 bytes. Bytestrings must
    be 0-terminated. See the docs:
    https://developer.gnome.org/glib/stable/gvariant-text.html#gvariant-text-bytestrings
    
    The existing API to create a GVariant with 'ay' type is `new
    GLib.Variant('ay', someByteArray)`. This remains unchanged, but this
    commit adds a new convenience API where you can pass a string instead of
    a byte array. If a string is passed in, the GVariant is assumed to be a
    bytestring, and so will be 0-terminated.
    
    The existing, probably unintended, behaviour of `new GLib.Variant('ay',
    someString)` was to always strip the 0-terminator, even if it was
    explicitly provided (`new GLib.Variant('ay', 'pizza\0')`). This is probably
    never what client code intended, but also that was not an actual API so
    technically the behaviour was undefined.
    
    Closes: #203

 installed-tests/js/testGLib.js | 21 +++++++++++++++++++++
 modules/overrides/GLib.js      | 14 ++++++++++++--
 2 files changed, 33 insertions(+), 2 deletions(-)
---
diff --git a/installed-tests/js/testGLib.js b/installed-tests/js/testGLib.js
index f7e80274..b162eee9 100644
--- a/installed-tests/js/testGLib.js
+++ b/installed-tests/js/testGLib.js
@@ -48,4 +48,25 @@ describe('GVariant constructor', function () {
         expect(ByteArray.toString(byteArrayVariant.deep_unpack()))
             .toEqual('pizza');
     });
+
+    it('constructs a byte array variant from a string', function () {
+        const byteArrayVariant = new GLib.Variant('ay', 'pizza');
+        expect(ByteArray.toString(byteArrayVariant.deep_unpack()))
+            .toEqual('pizza');
+    });
+
+    it('0-terminates a byte array variant constructed from a string', function () {
+        const byteArrayVariant = new GLib.Variant('ay', 'pizza');
+        const a = byteArrayVariant.deep_unpack();
+        [112, 105, 122, 122, 97, 0].forEach((val, ix) =>
+            expect(a[ix]).toEqual(val));
+    });
+
+    it('does not 0-terminate a byte array variant constructed from a Uint8Array', function () {
+        const byteArray = Uint8Array.from('pizza', c => c.charCodeAt(0));
+        const byteArrayVariant = new GLib.Variant('ay', byteArray);
+        const a = byteArrayVariant.deep_unpack();
+        [112, 105, 122, 122, 97].forEach((val, ix) =>
+            expect(a[ix]).toEqual(val));
+    });
 });
diff --git a/modules/overrides/GLib.js b/modules/overrides/GLib.js
index 3f247ea8..75b2d9d2 100644
--- a/modules/overrides/GLib.js
+++ b/modules/overrides/GLib.js
@@ -112,7 +112,7 @@ function _pack_variant(signature, value) {
            return GLib.Variant.new_maybe(null, _pack_variant(signature, value));
        else
            return GLib.Variant.new_maybe(new GLib.VariantType(_read_single_type(signature, false).join('')), 
null);
-    case 'a':
+    case 'a': {
        let arrayType = _read_single_type(signature, false);
        if (arrayType[0] == 's') {
            // special case for array of strings
@@ -120,8 +120,17 @@ function _pack_variant(signature, value) {
        }
        if (arrayType[0] == 'y') {
            // special case for array of bytes
+            let bytes;
+            if (typeof value === 'string') {
+                let byteArray = ByteArray.fromString(value);
+                if (byteArray[byteArray.length - 1] !== 0)
+                    byteArray = Uint8Array.of(...byteArray, 0);
+                bytes = ByteArray.toGBytes(byteArray);
+            } else {
+                bytes = _makeBytes(value);
+            }
            return GLib.Variant.new_from_bytes(new GLib.VariantType('ay'),
-                                               _makeBytes(value), true);
+                bytes, true);
        }
 
        let arrayValue = [];
@@ -140,6 +149,7 @@ function _pack_variant(signature, value) {
            }
        }
        return GLib.Variant.new_array(new GLib.VariantType(arrayType.join('')), arrayValue);
+    }
 
     case '(':
        let children = [ ];


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]