Add nom parsers for main types

[?]
Jan 10, 2021, 4:23 AM
JBZGFYVOKR3X2GH25SOOW3X7RKY6ZACESYFF5NO26PJFUP3XGXUAC

Dependencies

  • [2] BOFUYB6I Add documentation and implement some feedback from Discord (https://discord.com/channels/273534239310479360/354038657075904544/796256815024701480)
  • [3] 5II6T7YE Add gemini library

Change contents

  • edit in gemini/src/status.rs at line 228
    [3.4883]
    /// Parser
    #[cfg(feature = "parsers")]
    pub mod parse {
    use nom::{bytes::complete::take, combinator::map_res, error::context, IResult};
    use super::*;
    /// A simple `nom` parser for Gemini statuses based on `Status::from_bytes`.
    pub fn status(input: &[u8]) -> IResult<&[u8], Status> {
    context("status code", map_res(take(2usize), Status::from_bytes))(input)
    }
    }
  • replacement in gemini/src/response.rs at line 74
    [2.12150][2.12150:12214]()
    /// Return the response body as a utf-8 string, if present.
    [2.12150]
    [2.12214]
    /// Return the response body as a string, if present and valid utf-8.
    ///
    /// If you wish to allow invalid utf-8, call `body_bytes` and use the
    /// appropriate `String` function.
  • edit in gemini/src/response.rs at line 86
    [2.12491]
    [2.12491]
    }
    }
    /// Parser
    #[cfg(feature = "parsers")]
    pub mod parse {
    use nom::{
    combinator::{map_opt, rest},
    error::context,
    sequence::pair,
    IResult,
    };
    use super::*;
    use crate::header::parse::header;
    /// A `nom` parser for a response. Any bytes after the CRLF that separates
    /// the header from the response body will be considered part of the body.
    pub fn response(input: &[u8]) -> IResult<&[u8], Response> {
    context(
    "response",
    map_opt(pair(header, rest), |t| {
    if t.1.is_empty() {
    Response::new(t.0, None)
    } else {
    let v = Vec::from(t.1);
    Response::new(t.0, Some(v))
    }
    }),
    )(input)
  • edit in gemini/src/request.rs at line 90
    [3.7914]
    [3.7914]
    }
    }
    /// Parser
    #[cfg(feature = "parsers")]
    pub mod parse {
    use std::str;
    use nom::{
    bytes::complete::{tag, take_until},
    combinator::map_res,
    error::context,
    sequence::terminated,
    IResult,
    };
    use super::*;
    /// `nom` parser for a request string. Invalid utf-8 will be rejected, but
    /// non-"gemini://" urls are allowed as per the spec.
    pub fn request(input: &[u8]) -> IResult<&[u8], Request> {
    context(
    "request",
    map_res(terminated(take_until("\r\n"), tag("\r\n")), |bs| {
    let s = str::from_utf8(bs).map_err(|_| InvalidRequest::new())?;
    Request::from_uri(s)
    }),
    )(input)
  • edit in gemini/src/lib.rs at line 27
    [2.14400]
    #[cfg(feature = "parsers")]
    mod parse {
    use nom::{error::Error, Finish};
    use paste::paste;
    use crate::{header, request, response, status};
    macro_rules! parsers {
    ($(
    $(#[$doc:meta])*
    $name:ident: $type:ident
    ),*) => {
    $(
    paste! {
    $(#[$doc])*
    pub fn [< parse_ $name >]<'i>(input: impl AsRef<[u8]> + 'i) -> Result<$name::$type, Error<Vec<u8>>> {
    let bytes = input.as_ref();
    match $name::parse::$name(bytes).finish() {
    Ok((_, res)) => Ok(res),
    Err(Error { input, code }) => Err({
    let input = input.to_owned();
    Error { input, code }
    })
    }
    }
    }
    )*
    };
    }
    parsers!(
    /// Parse a `Header` from bytes.
    header: Header,
    /// Parse a `Request` from bytes.
    request: Request,
    /// Parse a `Response` from bytes.
    response: Response,
    /// Parse a `Status` from bytes.
    status: Status
    );
    }
    pub use parse::{parse_header, parse_request, parse_response, parse_status};
  • edit in gemini/src/header.rs at line 111
    [3.9724]
    /// Parser
    #[cfg(feature = "parsers")]
    pub mod parse {
    use nom::{
    bytes::complete::{tag, take_until},
    combinator::{map_opt, map_res},
    error::context,
    sequence::{terminated, tuple},
    IResult,
    };
    use super::*;
    use crate::status::parse::status;
    /// A `nom` parser for response headers. Fails on invalid utf-8.
    pub fn header(input: &[u8]) -> IResult<&[u8], Header> {
    let meta = map_res(take_until("\r\n"), |bs| {
    let v = Vec::from(bs);
    String::from_utf8(v)
    });
    context(
    "response header",
    map_opt(
    tuple((terminated(status, tag(" ")), terminated(meta, tag("\r\n")))),
    |t| Header::new(t.0, t.1),
    ),
    )(input)
    }
    }
  • edit in gemini/Cargo.toml at line 14
    [3.9950]
    [3.9950]
    [features]
    default = ["parsers"]
    parsers = ["nom", "paste"]
  • edit in gemini/Cargo.toml at line 21
    [3.9980]
    nom = { version = "6.0.1", optional = true }
    paste = { version = "1.0.4", optional = true }
  • edit in Cargo.lock at line 26
    [3.10764]
    [3.10764]
    [[package]]
    name = "arrayvec"
    version = "0.5.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
  • edit in Cargo.lock at line 75
    [3.11626]
    [3.11626]
    name = "bitvec"
    version = "0.19.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a7ba35e9565969edb811639dbebfe34edc0368e472c5018474c8eb2543397f81"
    dependencies = [
    "funty",
    "radium",
    "tap",
    "wyz",
    ]
    [[package]]
  • replacement in Cargo.lock at line 98
    [3.12006][3.12006:12014]()
    "nom",
    [3.12006]
    [3.12014]
    "nom 5.1.2",
  • edit in Cargo.lock at line 157
    [3.13283]
    [3.13283]
    name = "funty"
    version = "1.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
    [[package]]
  • edit in Cargo.lock at line 166
    [3.13334]
    [3.13334]
    "nom 6.0.1",
    "paste",
  • edit in Cargo.lock at line 217
    [3.14632]
    [3.14632]
    [[package]]
    name = "lexical-core"
    version = "0.7.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
    dependencies = [
    "arrayvec",
    "bitflags",
    "cfg-if",
    "ryu",
    "static_assertions",
    ]
  • edit in Cargo.lock at line 299
    [3.16376]
    [3.16376]
    name = "nom"
    version = "6.0.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "88034cfd6b4a0d54dd14f4a507eceee36c0b70e5a02236c4e4df571102be17f0"
    dependencies = [
    "bitvec",
    "lexical-core",
    "memchr",
    "version_check",
    ]
    [[package]]
  • edit in Cargo.lock at line 319
    [3.16599]
    [3.16599]
    [[package]]
    name = "paste"
    version = "1.0.4"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "c5d65c4d95931acda4498f675e332fcbdc9a06705cd07086c510e9b6009cd1c1"
  • edit in Cargo.lock at line 375
    [3.18052]
    [3.18052]
    name = "radium"
    version = "0.5.3"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
    [[package]]
  • edit in Cargo.lock at line 403
    [3.18700]
    [3.18700]
    [[package]]
    name = "ryu"
    version = "1.0.5"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
  • edit in Cargo.lock at line 427
    [3.19013]
    [3.19013]
    name = "static_assertions"
    version = "1.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
    [[package]]
  • edit in Cargo.lock at line 437
    [3.19190]
    [3.19190]
    [[package]]
    name = "tap"
    version = "1.0.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "36474e732d1affd3a6ed582781b3683df3d0563714c59c39591e8ff707cf078e"
  • edit in Cargo.lock at line 579
    [3.22955]
    [[package]]
    name = "wyz"
    version = "0.2.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"