Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ milo.setActiveCallbacks(parser, milo.CALLBACK_ACTIVE_ON_DATA)
buffer.set(message, 0)
milo.parse(parser, ptr, message.length)

// Use milo.parseWithError to get the consumed characters plus an error flag in a single call.

// Cleanup used resources.
milo.destroy(parser)
milo.dealloc(ptr, message.length)
Expand Down
17 changes: 17 additions & 0 deletions docs/js.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,23 @@ Parses `data` up to `limit` characters.

It returns the number of consumed characters.

#### `parseWithError(parser, data, limit)`

Parses `data` up to `limit` characters.

It returns an object containing the number of consumed characters and whether the parser errored:

```javascript
{
consumed: 0,
errored: false
}
```

Internally this wraps the `parse_with_error` WebAssembly export, which returns a signed 32-bit integer: `consumed` on success, and `-(consumed + 1)` on error. The extra `+ 1` allows representing errors that happen after consuming zero bytes.

Since the raw return value is a signed 32-bit integer, `parseWithError` supports up to `2_147_483_646` consumed bytes per call when an error is reported.

#### `reset(parser)`

Resets a parser. The second parameters specifies if to also reset the
Expand Down
14 changes: 14 additions & 0 deletions parser/src/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,20 @@ pub fn parse(parser: *mut c_void, data: *const c_uchar, limit: usize) -> usize {
unsafe { (*(parser as *mut Parser)).parse(data, limit) }
}

/// Parses a slice of characters. It returns consumed bytes, or -(consumed + 1)
/// if the parser errored.
#[unsafe(no_mangle)]
pub fn parse_with_error(parser: *mut c_void, data: *const c_uchar, limit: usize) -> i32 {
let parser = unsafe { &mut *(parser as *mut Parser) };
let consumed = parser.parse(data, limit) as i32;

if parser.error_code == crate::ERROR_NONE {
consumed
} else {
-(consumed + 1)
}
}

/// Pauses the parser. It will have to be resumed via `resume`.
#[unsafe(no_mangle)]
pub fn pause(parser: *mut c_void) { unsafe { (*(parser as *mut Parser)).pause() } }
Expand Down
11 changes: 11 additions & 0 deletions parser/src/wasm/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ function parse (parser, data, limit) {
return this.parse(parser, data, limit) >>> 0
}

function parseWithError (parser, data, limit) {
const result = this.parse_with_error(parser, data, limit) | 0
const errored = result < 0

return {
consumed: errored ? -result - 1 : result,
errored
}
}

function fail (parser, code, description) {
const len = description.length
const ptr = this.alloc(len)
Expand Down Expand Up @@ -102,6 +112,7 @@ export function setup (env = {}) {
create: create.bind(wasm),
destroy: destroy.bind(wasm),
parse: parse.bind(wasm),
parseWithError: parseWithError.bind(wasm),
fail: fail.bind(wasm),
hasDebug: hasDebug.bind(wasm),
clear: wasm.clear,
Expand Down
Loading