Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is position used in pipe? #2352

Closed
mariusGundersen opened this issue Apr 19, 2023 · 4 comments
Closed

Is position used in pipe? #2352

mariusGundersen opened this issue Apr 19, 2023 · 4 comments

Comments

@mariusGundersen
Copy link
Contributor

Based on #2350 (comment) I wanted to see what it would take to implement piping of strings. But looking at the pipe code I don't really follow how it works. There is a position number on the pipe object, but it's not actually used anywhere:

Espruino/src/jswrap_pipe.c

Lines 117 to 131 in 9d13de0

JsVar *buffer = jspExecuteFunction(readFunc, source, 1, &chunkSize);
if(buffer) {
JsVarInt bufferSize = jsvGetLength(buffer);
if (bufferSize>0) {
JsVar *response = jspExecuteFunction(writeFunc, destination, 1, &buffer);
if (jsvIsBoolean(response) && jsvGetBool(response)==false) {
// If boolean false was returned, wait for drain event (http://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback)
jsvObjectSetChildAndUnLock(pipe,"drainWait",jsvNewFromBool(true));
}
jsvUnLock(response);
jsvSetInteger(position, jsvGetInteger(position) + bufferSize);
}
jsvUnLock(buffer);
dataTransferred = true; // so we don't close the pipe if we get an empty string
}

read is only given a chunkSize, and write is given the buffer. It seams like the readable and writable streams handle their positioning themselves.

If I understand this correctly then position and all references to it (in the error messages) can be removed.

@gfwilliams
Copy link
Member

Yes, it does seem like position isn't needed.

However if we're adding the ability to pipe strings then maybe it would actually be needed for that?

@gfwilliams
Copy link
Member

Looking at this, while keep position we don't actually send 3 arguments to readFunc despite saying so in the error message - it's just the one for length.

We could send the extra 3 arguments and could then implement a read function for Strings, but I wonder whether sending the extra arguments might break piping for some other stuff, where read accepts other arguments?

It looks like it might be good to update the error messages, but to keep position and then in handlePipe we could handle the special case where the source was a string, and just call substring in it ourselves, using the position?

@mariusGundersen
Copy link
Contributor Author

mariusGundersen commented Apr 19, 2023

I think we should instead make a wrapper object for string that can handle the reading. That way E.pipe(string, destination) could wrap the string in a Stream object or you could do new Stream(string).pipe(destination) (where Stream is just an example, not sure what would be the best name for this thing). It seems dangerous to suddenly pass position to lots of places that don't use them today and expect them to behave correctly. It would also reduce the code and memory a bit to remove it.

The Stream class doesn't need much, it could be something like this:

class Stream {
  constructor(src){
    this.src = src;
    this.position = 0;
  }
  read(length){
    return this.src.substring(this.position, Math.min(this.position += length, this.src.length));
  }
}

@gfwilliams
Copy link
Member

Just done - that ended up being nice and easy. Not sure if there's any other object type it's worth wrapping that way too, like Arrays...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants