Skip to content

Commit

Permalink
Upgrade nom
Browse files Browse the repository at this point in the history
  • Loading branch information
efoerster committed Jun 4, 2019
1 parent 5de9cbd commit 2a4bc47
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 90 deletions.
34 changes: 31 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jsonrpc-derive = { path = "jsonrpc_derive" }
lazy_static = "1.3.0"
log = "0.4.6"
lsp-types = { git = "https://github.com/latex-lsp/lsp-types", rev = "8ce88a90c6753cf10d4b97d8cd6c9b8bb663c9d1", features = ["proposed"] }
nom = "4.2.3"
nom = "5.0.0-beta2"
path-clean = "0.1.0"
regex = "1.1.6"
reqwest = "0.9.16"
Expand Down
203 changes: 117 additions & 86 deletions src/codec.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use bytes::{BufMut, BytesMut};
use log::*;
use nom::*;
use std::io::{Error, ErrorKind};
use std::option::Option;
use std::str;
use std::string::String;
use tokio::codec::{Decoder, Encoder};

Expand All @@ -14,7 +12,7 @@ impl Decoder for LspCodec {
type Error = Error;

fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
match parse_message(src) {
match parser::parse(src) {
Ok((remaining, content)) => {
trace!("Received message:\n{}", content);

Expand Down Expand Up @@ -47,100 +45,133 @@ impl Encoder for LspCodec {
}
}

fn from_bytes(input: &[u8]) -> Result<usize, std::num::ParseIntError> {
usize::from_str_radix(str::from_utf8(input).unwrap(), 10)
}

named!(content_type<&[u8], ()>,
do_parse!(
tag!("Content-Type: application/vscode-jsonrpc;charset=utf") >>
opt!(tag!("-")) >>
tag!("8") >>
line_ending >>
()
)
);

named!(content_length<&[u8], usize>,
do_parse!(
tag!("Content-Length: ") >>
length: map_res!(take_while!(is_digit), from_bytes) >>
line_ending >>
(length)
)
);

named!(
parse_message<&[u8], String>,
do_parse!(
opt!(content_type) >>
length: content_length >>
opt!(content_type) >>
line_ending >>
content: map_res!(take!(length), str::from_utf8) >>
(content.to_string())
)
);

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_parse_content_type() {
let result = content_type(b"Content-Type: application/vscode-jsonrpc;charset=utf-8\r\n");
assert!(result.is_ok());
mod parser {
use nom::bytes::streaming::{tag, take, take_while};
use nom::character::is_digit;
use nom::character::streaming::line_ending;
use nom::combinator::{map_res, opt};
use nom::IResult;
use std::str;

pub fn parse(input: &[u8]) -> IResult<&[u8], String> {
let (input, _) = opt(content_type)(input)?;
let (input, length) = content_length(input)?;
let (input, _) = opt(content_type)(input)?;
let (input, _) = line_ending(input)?;
let (input, content) = map_res(take(length), str::from_utf8)(input)?;
Ok((input, content.to_owned()))
}

#[test]
fn test_parse_content_type_utf8() {
let result = content_type(b"Content-Type: application/vscode-jsonrpc;charset=utf8\r\n");
assert!(result.is_ok());
fn content_type(input: &[u8]) -> IResult<&[u8], &[u8]> {
let (input, _) = tag("Content-Type: application/vscode-jsonrpc;charset=utf")(input)?;
let (input, _) = opt(tag("-"))(input)?;
let (input, _) = tag("8")(input)?;
line_ending(input)
}

#[test]
fn test_parse_content_length() {
let result = content_length(b"Content-Length: 42\r\n");
assert_eq!(result.unwrap().1, 42usize);
fn content_length(input: &[u8]) -> IResult<&[u8], usize> {
let (input, _) = tag("Content-Length: ")(input)?;
let (input, length) = map_res(take_while(is_digit), from_bytes)(input)?;
let (input, _) = line_ending(input)?;
Ok((input, length))
}

#[test]
fn test_parse_message_full() {
let result = parse_message(
b"Content-Length: 2\r\nContent-Type: application/vscode-jsonrpc;charset=utf8\r\n\r\n{}",
);
assert_eq!(result.unwrap().1, "{}");
fn from_bytes(input: &[u8]) -> Result<usize, std::num::ParseIntError> {
usize::from_str_radix(str::from_utf8(input).unwrap(), 10)
}

#[test]
fn test_parse_message_type_first() {
let result = parse_message(
b"Content-Type: application/vscode-jsonrpc;charset=utf8\r\nContent-Length: 2\r\n\r\n{}",
);
assert_eq!(result.unwrap().1, "{}");
}
#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_parse_message_without_type() {
let result = parse_message(b"Content-Length: 2\r\n\r\n{}");
assert_eq!(result.unwrap().1, "{}");
}
#[test]
fn test_parse_content_type() {
let result =
content_type(b"Content-Type: application/vscode-jsonrpc;charset=utf-8\r\n");
assert!(result.is_ok());
}

#[test]
fn test_parse_message_incomplete() {
let result = parse_message(b"Content-Length:");
assert!(result.unwrap_err().is_incomplete());
}
#[test]
fn test_parse_content_type_utf8() {
let result = content_type(b"Content-Type: application/vscode-jsonrpc;charset=utf8\r\n");
assert!(result.is_ok());
}

#[test]
fn test_parse_message_invalid() {
let error = parse_message(b"foo").unwrap_err();
assert!(!error.is_incomplete());
}
#[test]
fn test_parse_content_length() {
let result = content_length(b"Content-Length: 42\r\n");
assert_eq!(result.unwrap().1, 42usize);
}

#[test]
fn test_parse_message_full() {
let result = parse(
b"Content-Length: 2\r\nContent-Type: application/vscode-jsonrpc;charset=utf8\r\n\r\n{}",
);
assert_eq!(result.unwrap().1, "{}");
}

#[test]
fn test_parse_message_overflow() {
let result = parse_message(b"Content-Length: 4\r\n\r\n{}");
assert!(result.unwrap_err().is_incomplete());
#[test]
fn test_parse_message_type_first() {
let result = parse(
b"Content-Type: application/vscode-jsonrpc;charset=utf8\r\nContent-Length: 2\r\n\r\n{}",
);
assert_eq!(result.unwrap().1, "{}");
}

#[test]
fn test_parse_message_without_type() {
let result = parse(b"Content-Length: 2\r\n\r\n{}");
assert_eq!(result.unwrap().1, "{}");
}

#[test]
fn test_parse_message_incomplete() {
let result = parse(b"Content-Length:");
assert!(result.unwrap_err().is_incomplete());
}

#[test]
fn test_parse_message_invalid() {
let error = parse(b"foo").unwrap_err();
assert!(!error.is_incomplete());
}

#[test]
fn test_parse_message_overflow() {
let result = parse(b"Content-Length: 4\r\n\r\n{}");
assert!(result.unwrap_err().is_incomplete());
}
}
}

//named!(content_type<&[u8], ()>,
// do_parse!(
// tag!("Content-Type: application/vscode-jsonrpc;charset=utf") >>
// opt!(tag!("-")) >>
// tag!("8") >>
// line_ending >>
// ()
// )
//);
//
//named!(content_length<&[u8], usize>,
// do_parse!(
// tag!("Content-Length: ") >>
// length: map_res!(take_while!(is_digit), from_bytes) >>
// line_ending >>
// (length)
// )
//);
//
//named!(
// parse_message<&[u8], String>,
// do_parse!(
// opt!(content_type) >>
// length: content_length >>
// opt!(content_type) >>
// line_ending >>
// content: map_res!(take!(length), str::from_utf8) >>
// (content.to_string())
// )
//);

0 comments on commit 2a4bc47

Please sign in to comment.