A sandbox to work on a Sōzu issue

Overview

Propagate error on nom.

Working on Sōzu issue #744.

What on earth did Geal mean when he wrote:

To propagate the error, you can use a custom error type that implements FromExternalError with serde_json errors: https://docs.rs/nom/7.1.0/nom/combinator/fn.map_res.html The map_res combinator is designed for that.

You will also need the cut combinator to transform the Error into a Failure, then the many0 combinator will return an error instead of stopping silently

Let's see what map_res does and how to slip in this cut thing.

Parse json into a struct

What Sōzu does:

use nom::{
    bytes::streaming::is_not,
    character::streaming::char,
    combinator::{complete, cut, map_res},
    multi::many0,
    sequence::terminated,
};

pub fn parse(input: &[u8]) -> IResult<&[u8], Vec<CommandRequest>> {
    use serde_json::from_slice;
    many0(complete(terminated(
        map_res(is_not("\0"), from_slice::<CommandRequest>),
        char('\0'),
    )))(input)
}

I want to reproduce this using a custom struct User that can be serialized and deserialized:

pub fn parse_several_users(input: &str) -> IResult<&str, Vec<User>> {
    many0(complete(terminated(
        map_res(is_not("\n"), serde_json::from_str::<User>),
        nom::character::complete::char('\n'),
    )))(input)
}

The goal is to make a proper use of cut and of a custom error, so that any serde_json error is converted to a failure and propagated into IResult.

Try it yourself

Feel free to cargo run to see what is wrong, and cargo test would be interesting too. Then dive into the code. Help me, Obi-Wan, you're my only hope.

The solution: split the code

It turns out the verbose way is more readable.

pub struct CustomError {
    kind: ErrorKind,
    serde_json_error: Option<serde_json::Error>,
}

impl FromExternalError<&str, serde_json::Error> for CustomError {
    // boilerplate
}

impl nom::error::ParseError<&str> for CustomError {
    // boilerplate
}

pub fn parse_one_user(input: &str) -> IResult<&str, User, CustomError> {
    let (i, json_data) = is_not("\n")(input)?;

    let user = match serde_json::from_str::<User>(json_data) {
        Ok(user) => user,
        Err(serde_error) => {
            return Err(nom::Err::Failure(CustomError::from_external_error(
                input,
                ErrorKind::MapRes,
                serde_error,
            )))
        }
    };

    let (next_input, _) = nom::character::complete::char('\n')(i)?;

    Ok((next_input, user))
}

pub fn parse_several_users(input: &str) -> IResult<&str, Vec<User>, CustomError> {
    many0(parse_one_user)(input)
}

Thank you @geal, eternal gratitude.

You might also like...
A sandbox library for making FAST voxel games

voxelize WIP A well-optimized web-based voxel engine. Development Before starting, make sure to install the following: rust node.js cargo-watch # clon

Manage light-weight sandbox environments for development

Cubicle development container manager Cubicle is a program to manage containers or sandbox environments. It is intended for isolating development envi

A lightweight sandbox sim written in Rust.
A lightweight sandbox sim written in Rust.

Rusty Sandbox A lightweight sandbox sim written in Rust. Play via Browser (WASM) | Compile by yourself This is a quick hobby project written to practi

A template project for building a database-driven microservice in Rust and run it in the WasmEdge sandbox.

Secure & lightweight microservice with a database backend In this repo, we demonstrate a microservice written in Rust, and connected to a MySQL databa

An online judge sandbox server in Rust, inspired by go-judge, for SAST OJ.

RsJudge An online judge sandbox server in Rust, inspired by go-judge, for SAST OJ. Table of Contents Features Build from source Prerequisites Build Fe

A work-in-progress, open-source, multi-player city simulation game.
A work-in-progress, open-source, multi-player city simulation game.

Citybound is a city building game with a focus on realism, collaborative planning and simulation of microscopic details. It is independently developed

A library to work with CIDRs in rust

ipnetwork This is a library to work with IPv4 and IPv6 CIDRs in Rust Run Clippy by doing rustup component add clippy cargo clippy Installation This c

A fast monadic-style parser combinator designed to work on stable Rust.

Chomp Chomp is a fast monadic-style parser combinator library designed to work on stable Rust. It was written as the culmination of the experiments de

CLI tool to work with Sled key-value databases.

sledtool CLI tool to work with Sled key-value databases. $ sledtool --help Usage: sledtool dbpath command [args] CLI tool to work with Sled da

transmute-free Rust library to work with the Arrow format

Arrow2: Transmute-free Arrow This repository contains a Rust library to work with the Arrow format. It is a re-write of the official Arrow crate using

a handy utility to work with encrypted DMGs

edmgutil edmgutil is a simple wrapper utility to hdiutil to help you work with disposable, encrypted DMGs. It can decompress an encrypted ZIP into a n

Diana is a GraphQL system for Rust that's designed to work as simply as possible out of the box

Diana is a GraphQL system for Rust that's designed to work as simply as possible out of the box, without sacrificing configuration ability. Unlike other GraphQL systems, Diana fully supports serverless functions and automatically integrates them with a serverful subscriptions system as needed, and over an authenticated channel. GraphQL subscriptions are stateful, and so have to be run in a serverful way. Diana makes this process as simple as possible.

Beanstalk is a simple, fast work queue.

beanstalkd Simple and fast general purpose work queue.

Driver to work with the esp8266 module over the serial port.

esp8266-wifi-serial (WIP) Driver to work with the esp8266 module over the serial port. By using this module you can join the existing access point or

Utility library to work with tuples.

Utility library to work with tuples.

Rust implementation of AstroBWT Proof-Of-Work algorithm

AstroBWT AstroBWT is a proof-of-work (PoW) algorithm based on Burrows-Wheeler transform (BWT). Developed and used by the DERO Project for Mobile (arm)

Bell is a work in progress programming language that compiles to MCfunction (Minecraft's language for creating datapacks).

Bell is a work in progress programming language that compiles to MCfunction (Minecraft's language for creating datapacks). It provides a higher level,

A lite tool to make systemd work in any container(Windows Subsystem for Linux 2, Docker, Podman, etc.)

Angea Naming from hydrangea(アジサイ) A lite tool to make systemd work in any container(Windows Subsystem for Linux 2, Docker, Podman, etc.) WSL1 is not s

A lite tool to make systemd work in any container(Windows Subsystem for Linux 2, Docker, Podman, etc.)

Angea Naming from hydrangea(アジサイ) A lite tool to make systemd work in any container(Windows Subsystem for Linux 2, Docker, Podman, etc.) WSL1 is not s

Owner
Emmanuel Bosquet
Readme evangelist. Back-end apprentice at Clever Cloud.
Emmanuel Bosquet
Demonstration of an issue with cargo-udeps

the setup lib1 exports a function lib2 contains a dependency to lib1, and calls into lib1's method binary contains a dependency to lib2, and uses it b

Benjamin Bouvier 1 Nov 28, 2021
Help project managers and project owners with easy-to-understand views of github issue dependencies.

Help project managers and project owners with easy-to-understand views of github issue dependencies.

nasa 56 Dec 15, 2022
Simple PoC to issue JSON Web Tokens (JWTs) with a canister on the Internet Computer.

JWT Issuer Proof of Concept Overview Simple PoC to issue JSON Web Tokens (JWTs) with a canister on the Internet Computer. It allows the issuance of tw

Dominic Wörner 7 Oct 13, 2022
A plain-text Issue and PR tracking system

Markrequests A plain-text Issue and PR tracking system. An example of a file to track these is in prs/example.md Rationale I am unsatisfied with the c

Tristram Oaten 11 Dec 11, 2023
Vulkan rendering sandbox for raytracing

sol-rs ☀ sol-rs is a small rendering toolkit for Vulkan, with a focus on real-time raytracing (which is not currently available via other APIs such as

Éric Renaud-Houde 65 Dec 7, 2022
sandbox to play around numerous functionalities on Solana

Solana Sandbox This sandbox is for verifying smart contracts(programs) implemented on Solana for a self-study purpose. Programs Currently implemented

Tomoaki Imai 22 May 11, 2022
Dragonball-sandbox is a collection of Rust crates to help build custom Virtual Machine Monitors and hypervisors

Dragonball-sandbox is a collection of Rust crates to help build custom Virtual Machine Monitors and hypervisors. The crates here are considered to be the downstream of rust-vmm.

OpenAnolis Community 62 Dec 30, 2022
Sandbox is a pixel physics simulator inspired by other such like Sandspiel and Noita

Sandbox Sandbox is a pixel physics simulator inspired by other such like Sandspiel and Noita. It's also a precursor for an ongoing game project. Sandb

Okko Hakola 76 Nov 3, 2022
Cryptocurrencies trend-following trading bot sandbox written in Rust.

Trend trading bot Experiments repo about (crypto) trend trading. By "trend" I mean trading following the trend using technical indicators (vs other ki

Julien 6 Oct 2, 2022
Rust Sandbox [code for 15 concepts of Rust language]

Rust-Programming-Tutorial Rust Sandbox [code for 15 concepts of Rust language]. The first time I've been introduced to Rust was on January 2022, you m

Bek Brace 4 Aug 30, 2022