Hi Andrea,

I've come up with something that... almost does what you're looking at
here. Perhaps it's useful as a guide of what one can do with the Gio
interface.

I think you may hit some awkward problems with modelling Node-style streams
with GLib ones. But perhaps it is possible and this helps. I don't really
know the Node stream semantics so I have assumed various things in my
Readable implementation as you'll see... Note that MemoryInputStream really
is just a byte stream; so there is no guarantee you'll receive the exact
block of bytes that was written -- for example, when I run this I get a
first chunk of "12", followed by "3", "4", etc.


let Gio = imports.gi.Gio;
let byteArray = imports.byteArray;
let mainloop = imports.mainloop;

class Readable {
  constructor() {
    this._mio = Gio.MemoryInputStream.new();
    this._callbacks = {};
    this._startNext();
  }

  _startNext() {
    // Enqueue an async read; and re-enqueue when it finishes, so we're
    // always waiting for data...
    this._mio.read_bytes_async(4096, 1, null, (source, res) => {
this._onData(this._mio.read_bytes_finish(res));
        this._startNext();
});
  }

  _onData(bytes) {
    if (this._callbacks['data']) {
      let ba = byteArray.fromGBytes(bytes);
      this._callbacks['data'](ba);
      this._read();
    }
  }

  push(bytes) {
    if (bytes == null) {
      mainloop.quit('main');
      return;
    }
    this._mio.add_bytes(bytes);
  }

  on(name, callback) {
    this._callbacks[name] = callback;
    if (name === 'data') {
      this._read();
    }
  }
}

class Counter extends Readable {
  constructor(opt) {
    super(opt);
    this._max = 1000;
    this._index = 1;
  }

  _read() {
    const i = this._index++;
    if (i > this._max)
      this.push(null);
    else {
      const str = '' + i;
      const buf = byteArray.fromString(str); // Buffer.from(str, 'ascii');
      this.push(buf);
    }
  }
}

(new Counter).on('data', (str) => {
    print("data", str.toString());
});

mainloop.run('main');


On 7 November 2017 at 10:08, Andrea Giammarchi <andrea.giammar...@gmail.com>
wrote:

> I am trying to implement a stream module and apparently I have everything
> I need but practically I'm unable to use streams.
>
> If I instantiate a `new Gio.InputStream` I have the following error:
> cannot create instance of abstract (non-instantiatable) type 'GInputStream'
>
> I cannot even extend it ... so I've though "ok, maybe it's like an
> interface, I implement it and that's it"
>
> But then a JS class wouldn't work as base_stream for a
> Gio.BufferedInputStream, and if I extend the JS class to be a
> GObject.Object then:
> Gjs-WARNING **: JS ERROR: TypeError: Object is of type GObject.Object -
> cannot convert to GInputStream
>
> where GInputStream is the one I cannot use in the first place.
>
> I've reached full circle then so ... I wonder if anyone has any idea how
> to use/create/extend streams in GJS (not talking about file streams but
> streams in general) or if it's even possible.
>
> In node, as example, I could do this and it will work:
>
> ```js
>
> const { Readable } = require('stream');
>
> class Counter extends Readable {
> constructor(opt) {
> super(opt);
> this._max = 1000;
> this._index = 1;
> }
>
> _read() {
> const i = this._index++;
> if (i > this._max)
> this.push(null);
> else {
> const str = '' + i;
> const buf = Buffer.from(str, 'ascii');
> this.push(buf);
> }
> }
> }
>
> (new Counter).on('data', console.log);
>
> ```
>
> _______________________________________________
> javascript-list mailing list
> javascript-list@gnome.org
> https://mail.gnome.org/mailman/listinfo/javascript-list
>
>
_______________________________________________
javascript-list mailing list
javascript-list@gnome.org
https://mail.gnome.org/mailman/listinfo/javascript-list

Reply via email to