Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
hansihe committed Apr 25, 2017
1 parent 0af18c7 commit 407d6e0
Show file tree
Hide file tree
Showing 26 changed files with 841 additions and 232 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ erl_crash.dump
*.ez

/priv/native/*

/native/juicy_native/target/
19 changes: 19 additions & 0 deletions lib/juicy.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,33 @@ defmodule Juicy do
Documentation for Juicy.
"""

@type ejson :: any
@type error :: any

@doc """
The simplest and most basic parse function.
Will parse the input binary into ejson. Will return an error tuple if there are any
errors in the input.
This is the fastest parse function, as it does not need to walk a spec tree.
"""
@spec parse(binary) :: {:ok, ejson} | {:error, error}
def parse(binary) do
Juicy.Basic.parse(binary)
end

@spec parse_spec(binary, Juicy.Spec.t) :: {:ok, any} | {:error, error}
def parse_spec(binary, spec) do
Juicy.Basic.parse_spec(binary, spec)
end

@spec parse_stream(Stream.t, Juicy.Spec.t) :: Stream.t
def parse_stream(stream, spec) do
Juicy.Stream.stream(stream, spec)
end

@spec validate_spec(Juicy.Spec.t) :: boolean
def validate_spec(spec) do
Juicy.Native.validate_spec(spec)
end
Expand Down
13 changes: 11 additions & 2 deletions lib/juicy/basic.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
defmodule Juicy.Basic do
@moduledoc false

def parse(binary) do
handle_parse_return(binary, Juicy.Native.parse_init(binary))
Expand All @@ -7,8 +8,16 @@ defmodule Juicy.Basic do
defp handle_parse_return(binary, {:iter, stack, res}) do
handle_parse_return(binary, Juicy.Native.parse_iter(binary, stack, res))
end
defp handle_parse_return(_, ret) do
ret
defp handle_parse_return(_, ret), do: ret

def parse_spec(binary, spec) do
{:ok, state} = Juicy.Native.spec_parse_init(binary, spec)
handle_parse_spec_return(Juicy.Native.spec_parse_iter(state))
end

defp handle_parse_spec_return({:iter, state}) do
handle_parse_spec_return(Juicy.Native.spec_parse_iter(state))
end
defp handle_parse_spec_return(resp), do: resp

end
5 changes: 5 additions & 0 deletions lib/juicy/native.ex
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
defmodule Juicy.Native do
@moduledoc false

use Rustler, otp_app: :juicy, crate: "juicy_native"

def parse_init(_), do: err()
def parse_iter(_, _, _), do: err()

def spec_parse_init(_, _), do: err()
def spec_parse_iter(_), do: err()

def stream_parse_init(_), do: err()
def stream_parse_iter(_, _), do: err()

Expand Down
5 changes: 5 additions & 0 deletions lib/juicy/spec.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule Juicy.Spec do

@type t :: any

end
3 changes: 2 additions & 1 deletion lib/juicy/stream.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
defmodule Juicy.Stream do
@moduledoc false

defstruct reader: nil, spec: nil, binaries: nil, parser: nil, output_queue: [], state: {:read_input, :parsing_not_done, nil}

Expand Down Expand Up @@ -32,7 +33,7 @@ defimpl Enumerable, for: Juicy.Stream do
def count(_stream) do
{:error, __MODULE__}
end
def member?(_stream) do
def member?(_stream, _element) do
{:error, __MODULE__}
end

Expand Down
3 changes: 2 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ defmodule Juicy.Mixfile do
#
# Type "mix help deps" for more examples and options
defp deps do
[{:rustler, "~> 0.8.0"}]
[{:rustler, "~> 0.8.0"},
{:ex_doc, "~> 0.14", only: :dev, runtime: false}]
end

defp rustler_crates do
Expand Down
4 changes: 3 additions & 1 deletion mix.lock
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
%{"rustler": {:hex, :rustler, "0.8.0", "337e2b39c80dafb4a5d65d7791a9a97b3d566941bdb5c718d33488025e0299b0", [:mix], []}}
%{"earmark": {:hex, :earmark, "1.1.1", "433136b7f2e99cde88b745b3a0cfc3fbc81fe58b918a09b40fce7f00db4d8187", [:mix], []},
"ex_doc": {:hex, :ex_doc, "0.15.0", "e73333785eef3488cf9144a6e847d3d647e67d02bd6fdac500687854dd5c599f", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, optional: false]}]},
"rustler": {:hex, :rustler, "0.8.0", "337e2b39c80dafb4a5d65d7791a9a97b3d566941bdb5c718d33488025e0299b0", [:mix], []}}
30 changes: 15 additions & 15 deletions native/juicy_native/Cargo.lock

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

6 changes: 3 additions & 3 deletions native/juicy_native/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ path = "src/lib.rs"
crate-type = ["dylib"]

[dependencies]
rustler = { path = "../../../Rustler" }
rustler_codegen = "0.13.0"
rustler = "0.14.0"
rustler_codegen = "0.14.0"
lazy_static = "0.2"

num-traits = "0.1"
num-bigint = "0.1"

iterative_json_parser = { path = "../../../rust_iterative_json_parser/" }
iterative_json_parser = { git = "https://github.com/hansihe/rust_iterative_json_parser" }

[profile.release]
debug = true
Expand Down
54 changes: 23 additions & 31 deletions native/juicy_native/src/basic.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use iterative_json_parser::{Parser, Source, PeekResult, Sink, Range, Pos, NumberData, ParseError,
Unexpected, Bailable, SourceSink, BailVariant, Position,
StringPosition};
Unexpected, Bailable, Position, StringPosition};

use rustler::{NifEnv, NifTerm, NifResult, NifEncoder};
use rustler::resource::ResourceArc;
Expand All @@ -10,6 +9,8 @@ use rustler::types::binary::OwnedNifBinary;

use ::strings::BuildString;
use ::numbers::number_data_to_term;
use ::input_provider::InputProvider;
use ::input_provider::single::SingleBinaryProvider;

use std::io::Write;
use std::sync::Mutex;
Expand All @@ -18,8 +19,7 @@ use std::ops::DerefMut;
struct BasicSS<'a, 'b> {
env: NifEnv<'a>,

source: &'a [u8],
source_binary: NifBinary<'a>,
input: SingleBinaryProvider<'a>,

position: usize,
next_reschedule: usize,
Expand All @@ -41,19 +41,20 @@ impl<'a, 'b> Source for BasicSS<'a, 'b> {
fn peek_char(&mut self) -> PeekResult<()> {
if self.position == self.next_reschedule {
PeekResult::Bail(())
} else if self.position < self.source.len() {
PeekResult::Ok(self.source[self.position])
} else if let Some(character) = self.input.byte(self.position) {
PeekResult::Ok(character)
} else {
PeekResult::Eof
}
}
fn peek_slice<'c>(&'c self, length: usize) -> Option<&'c [u8]> {
let (_, slice) = self.source.split_at(self.position);
if slice.len() >= length {
Some(slice)
} else {
None
}
fn peek_slice<'c>(&'c self, _length: usize) -> Option<&'c [u8]> {
// let (_, slice) = self.source.split_at(self.position);
// if slice.len() >= length {
// Some(slice)
// else {
// None
//
None
}
}

Expand All @@ -67,7 +68,7 @@ impl<'a, 'b> Sink for BasicSS<'a, 'b> {
}
fn push_number(&mut self, _pos: Position, num: NumberData) -> Result<(), Self::Bail> {
let term = number_data_to_term(self.env, num, |r, b| {
b.extend_from_slice(&self.source[r.start..r.end]);
self.input.push_range(r, b);
});
self.out_stack.push(term);
Ok(())
Expand All @@ -85,33 +86,27 @@ impl<'a, 'b> Sink for BasicSS<'a, 'b> {
*self.current_string = BuildString::new();
}
fn append_string_range(&mut self, range: Range) {
let source = self.source;
let input = &self.input;
self.current_string.append_range(range, |r, b| {
b.extend_from_slice(&source[r.start..r.end]);
input.push_range(r, b);
});
}
fn append_string_single(&mut self, character: u8) {
let source = self.source;
let input = &self.input;
self.current_string.append_single(character, |r, b| {
b.extend_from_slice(&source[r.start..r.end]);
input.push_range(r, b);
});
}
fn append_string_codepoint(&mut self, codepoint: char) {
let source = self.source;
let input = &self.input;
self.current_string.append_codepoint(codepoint, |r, b| {
b.extend_from_slice(&source[r.start..r.end]);
input.push_range(r, b);
});
}
fn finalize_string(&mut self, _pos: StringPosition) -> Result<(), Self::Bail> {
let string_term = match *self.current_string {
BuildString::None => "".encode(self.env),
BuildString::Range(range) => {
self.source_binary
.make_subbinary(range.start, range.end - range.start)
.ok()
.unwrap()
.encode(self.env)
}
BuildString::Range(range) => self.input.range_to_term(self.env, range),
BuildString::Owned(ref buf) => {
let mut bin = OwnedNifBinary::new(buf.len()).unwrap();
bin.as_mut_slice().write(buf).unwrap();
Expand Down Expand Up @@ -167,12 +162,9 @@ fn parse_inner<'a>(env: NifEnv<'a>,
stack: Vec<NifTerm<'a>>,
iter_state: &mut IterState)
-> Result<NifTerm<'a>, Vec<NifTerm<'a>>> {
let input_slice = input.as_slice();

let mut ss = BasicSS {
env: env,
source: input_slice,
source_binary: input,
input: SingleBinaryProvider::new(input),
position: iter_state.source_pos,
next_reschedule: iter_state.source_pos + 40_000,
out_stack: stack,
Expand Down
Loading

0 comments on commit 407d6e0

Please sign in to comment.