Switch to using couch_mrview data structures and utility functions

This updates the data structures expected for view callbacks, mainly
switching total_and_offset to the new meta response, and also slight
modifications to the expected row format.

Additionally this removes view logic from fabric that is better
handled in couch_mrview.
diff --git a/src/fabric.erl b/src/fabric.erl
index 1f05ed6..5be6f49 100644
--- a/src/fabric.erl
+++ b/src/fabric.erl
@@ -278,15 +278,31 @@
 -spec query_view(dbname(), #doc{} | binary(), iodata(), callback(), any(),
         #mrargs{}) ->
     any().
-query_view(DbName, Design, ViewName, Callback, Acc0, QueryArgs) ->
+query_view(DbName, GroupId, ViewName, Callback, Acc0, QueryArgs)
+        when is_binary(GroupId) ->
+    {ok, DDoc} = ddoc_cache:open(DbName, <<"_design/", GroupId/binary>>),
+    query_view(DbName, DDoc, ViewName, Callback, Acc0, QueryArgs);
+query_view(DbName, DDoc, ViewName, Callback, Acc0, QueryArgs0) ->
     Db = dbname(DbName), View = name(ViewName),
-    case is_reduce_view(Db, Design, View, QueryArgs) of
-    true ->
-        Mod = fabric_view_reduce;
-    false ->
-        Mod = fabric_view_map
-    end,
-    Mod:go(Db, Design, View, QueryArgs, Callback, Acc0).
+    {ok, #mrst{views=Views, language=Lang}} =
+        couch_mrview_util:ddoc_to_mrst(Db, DDoc),
+    QueryArgs1 = couch_mrview_util:set_view_type(QueryArgs0, View, Views),
+    QueryArgs2 = couch_mrview_util:validate_args(QueryArgs1),
+    VInfo = couch_mrview_util:extract_view(Lang, QueryArgs2, View, Views),
+    case is_reduce_view(QueryArgs2) of
+        true ->
+            fabric_view_reduce:go(
+                Db,
+                DDoc,
+                View,
+                QueryArgs2,
+                Callback,
+                Acc0,
+                VInfo
+            );
+        false ->
+            fabric_view_map:go(Db, DDoc, View, QueryArgs2, Callback, Acc0)
+    end.
 
 %% @doc retrieve info about a view group, disk size, language, whether compaction
 %%      is running and so forth
@@ -313,9 +329,9 @@
         end_key = <<"_design0">>,
         include_docs=true
     },
-    Callback = fun({total_and_offset, _, _}, []) ->
+    Callback = fun({meta, _}, []) ->
         {ok, []};
-    ({row, {Props}}, Acc) ->
+    ({row, Props}, Acc) ->
         case couch_util:get_value(id, Props) of
         <<"_design/", _/binary>> ->
             {ok, [couch_util:get_value(doc, Props) | Acc]};
@@ -437,8 +453,10 @@
 default_callback(Row, Acc) ->
     {ok, [Row | Acc]}.
 
-is_reduce_view(_, _, _, #mrargs{view_type=Reduce}) ->
-    Reduce =:= reduce.
+is_reduce_view(#mrargs{view_type=ViewType}) ->
+    ViewType =:= red;
+is_reduce_view({Reduce, _, _}) ->
+    Reduce =:= red.
 
 %% @doc convenience method for use in the shell, converts a keylist
 %%      to a `changes_args' record
diff --git a/src/fabric_group_info.erl b/src/fabric_group_info.erl
index 135090f..5325f76 100644
--- a/src/fabric_group_info.erl
+++ b/src/fabric_group_info.erl
@@ -22,10 +22,9 @@
     {ok, DDoc} = fabric:open_doc(DbName, GroupId, []),
     go(DbName, DDoc);
 
-go(DbName, #doc{} = DDoc) ->
-    Group = couch_view_group:design_doc_to_view_group(DDoc),
+go(DbName, #doc{id=DDocId}) ->
     Shards = mem3:shards(DbName),
-    Workers = fabric_util:submit_jobs(Shards, group_info, [Group]),
+    Workers = fabric_util:submit_jobs(Shards, group_info, [DDocId]),
     RexiMon = fabric_util:create_monitors(Shards),
     Acc0 = {fabric_dict:init(Workers, nil), []},
     try
diff --git a/src/fabric_rpc.erl b/src/fabric_rpc.erl
index 3f4f8d2..cee3c55 100644
--- a/src/fabric_rpc.erl
+++ b/src/fabric_rpc.erl
@@ -24,18 +24,6 @@
 -include_lib("couch/include/couch_db.hrl").
 -include_lib("couch_mrview/include/couch_mrview.hrl").
 
--record (view_acc, {
-    db,
-    limit,
-    include_docs,
-    conflicts,
-    doc_info = nil,
-    offset = nil,
-    total_rows,
-    reduce_fun = fun couch_db:enum_docs_reduce_to_count/1,
-    group_level = 0
-}).
-
 %% rpc endpoints
 %%  call to with_db will supply your M:F with a #db{} and then remaining args
 
diff --git a/src/fabric_view.erl b/src/fabric_view.erl
index d0c6e45..31c25d9 100644
--- a/src/fabric_view.erl
+++ b/src/fabric_view.erl
@@ -224,7 +224,10 @@
     Counters1 = fabric_dict:update_counter(Worker, -1, Counters0),
     {Row, State#collector{rows = Rest, counters=Counters1}}.
 
+%% TODO: rectify nil <-> undefined discrepancies
 find_next_key(nil, Dir, RowDict) ->
+    find_next_key(undefined, Dir, RowDict);
+find_next_key(undefined, Dir, RowDict) ->
     case lists:sort(sort_fun(Dir), dict:fetch_keys(RowDict)) of
     [] ->
         throw(complete);
@@ -237,21 +240,21 @@
     {Key, Rest}.
 
 transform_row(#view_row{key=Key, id=reduced, value=Value}) ->
-    {row, {[{key,Key}, {value,Value}]}};
+    {row, [{key,Key}, {value,Value}]};
 transform_row(#view_row{key=Key, id=undefined}) ->
-    {row, {[{key,Key}, {error,not_found}]}};
+    {row, [{key,Key}, {id,error}, {value,not_found}]};
 transform_row(#view_row{key=Key, id=Id, value=Value, doc=undefined}) ->
-    {row, {[{id,Id}, {key,Key}, {value,Value}]}};
-transform_row(#view_row{key=Key, id=Id, value=Value, doc={error,Reason}}) ->
-    {row, {[{id,Id}, {key,Key}, {value,Value}, {error,Reason}]}};
+    {row, [{id,Id}, {key,Key}, {value,Value}]};
+transform_row(#view_row{key=Key, id=_Id, value=_Value, doc={error,Reason}}) ->
+    {row, [{id,error}, {key,Key}, {value,Reason}]};
 transform_row(#view_row{key=Key, id=Id, value=Value, doc=Doc}) ->
-    {row, {[{id,Id}, {key,Key}, {value,Value}, {doc,Doc}]}}.
+    {row, [{id,Id}, {key,Key}, {value,Value}, {doc,Doc}]}.
 
 
 sort_fun(fwd) ->
-    fun(A,A) -> true; (A,B) -> couch_view:less_json(A,B) end;
+    fun(A,A) -> true; (A,B) -> couch_ejson_compare:less_json(A,B) end;
 sort_fun(rev) ->
-    fun(A,A) -> true; (A,B) -> couch_view:less_json(B,A) end.
+    fun(A,A) -> true; (A,B) -> couch_ejson_compare:less_json(B,A) end.
 
 extract_view(Pid, ViewName, [], _ViewType) ->
     couch_log:error("missing_named_view ~p", [ViewName]),
diff --git a/src/fabric_view_all_docs.erl b/src/fabric_view_all_docs.erl
index 1415c82..701afa7 100644
--- a/src/fabric_view_all_docs.erl
+++ b/src/fabric_view_all_docs.erl
@@ -72,7 +72,7 @@
         false -> Keys2
     end,
     receive {'DOWN', Ref0, _, _, {ok, TotalRows}} ->
-        {ok, Acc1} = Callback({total_and_offset, TotalRows, 0}, Acc0),
+        {ok, Acc1} = Callback({meta, [{total, TotalRows}]}, Acc0),
         {ok, Acc2} = doc_receive_loop(
             Keys3, queue:new(), SpawnFun, MaxJobs, Callback, Acc1
         ),
@@ -95,7 +95,9 @@
         {error, Resp}
     end;
 
-handle_message({total_and_offset, Tot, Off}, {Worker, From}, State) ->
+handle_message({meta, Meta0}, {Worker, From}, State) ->
+    Tot = couch_util:get_value(total, Meta0, 0),
+    Off = couch_util:get_value(offset, Meta0, 0),
     #collector{
         callback = Callback,
         counters = Counters0,
@@ -123,7 +125,8 @@
             }};
         false ->
             FinalOffset = erlang:min(Total, Offset+State#collector.skip),
-            {Go, Acc} = Callback({total_and_offset, Total, FinalOffset}, AccIn),
+            Meta = [{total, Total}, {offset, FinalOffset}],
+            {Go, Acc} = Callback({meta, Meta}, AccIn),
             {Go, State#collector{
                 counters = fabric_dict:decrement_all(Counters2),
                 total_rows = Total,
diff --git a/src/fabric_view_map.erl b/src/fabric_view_map.erl
index 9e41c11..eb30179 100644
--- a/src/fabric_view_map.erl
+++ b/src/fabric_view_map.erl
@@ -66,7 +66,9 @@
         {error, Resp}
     end;
 
-handle_message({total_and_offset, Tot, Off}, {Worker, From}, State) ->
+handle_message({meta, Meta0}, {Worker, From}, State) ->
+    Tot = couch_util:get_value(total, Meta0, 0),
+    Off = couch_util:get_value(offset, Meta0, 0),
     #collector{
         callback = Callback,
         counters = Counters0,
@@ -94,7 +96,8 @@
             }};
         false ->
             FinalOffset = erlang:min(Total, Offset+State#collector.skip),
-            {Go, Acc} = Callback({total_and_offset, Total, FinalOffset}, AccIn),
+            Meta = [{total, Total}, {offset, FinalOffset}],
+            {Go, Acc} = Callback({meta, Meta}, AccIn),
             {Go, State#collector{
                 counters = fabric_dict:decrement_all(Counters2),
                 total_rows = Total,
@@ -133,11 +136,11 @@
 
 merge_row(fwd, undefined, Row, Rows) ->
     lists:merge(fun(#view_row{key=KeyA, id=IdA}, #view_row{key=KeyB, id=IdB}) ->
-        couch_view:less_json([KeyA, IdA], [KeyB, IdB])
+        couch_ejson_compare:less_json_ids({KeyA, IdA}, {KeyB, IdB})
     end, [Row], Rows);
 merge_row(rev, undefined, Row, Rows) ->
     lists:merge(fun(#view_row{key=KeyA, id=IdA}, #view_row{key=KeyB, id=IdB}) ->
-        couch_view:less_json([KeyB, IdB], [KeyA, IdA])
+        couch_ejson_compare:less_json_ids({KeyB, IdB}, {KeyA, IdA})
     end, [Row], Rows);
 merge_row(_, KeyDict, Row, Rows) ->
     lists:merge(fun(#view_row{key=A, id=IdA}, #view_row{key=B, id=IdB}) ->