{"action":"created","comment":{"url":"https://api.github.com/repos/mozilla/mentat/pulls/comments/109059135","pull_request_review_id":30136024,"id":109059135,"diff_hunk":"@@ -0,0 +1,282 @@\n+// Copyright 2016 Mozilla\n+//\n+// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n+// this file except in compliance with the License. You may obtain a copy of the\n+// License at http://www.apache.org/licenses/LICENSE-2.0\n+// Unless required by applicable law or agreed to in writing, software distributed\n+// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n+// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n+// specific language governing permissions and limitations under the License.\n+\n+use std;\n+use std::fmt::{Display, Formatter};\n+use std::cmp::Ordering;\n+\n+use combine::{\n+    ConsumedResult,\n+    ParseError,\n+    Parser,\n+    StreamOnce,\n+    eof,\n+    satisfy,\n+    satisfy_map,\n+};\n+use combine::primitives;\n+use combine::primitives::{\n+    FastResult,\n+};\n+use combine::combinator::{\n+    Eof,\n+    Skip,\n+};\n+\n+use edn;\n+\n+/// A wrapper to let us order `edn::Span` in whatever way is appropriate for parsing with `combine`.\n+#[derive(Clone, Debug)]\n+pub struct SpanPosition(edn::Span);\n+\n+impl Display for SpanPosition {\n+    fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result {\n+        write!(f, \"{:?}\", self.0)\n+    }\n+}\n+\n+impl PartialEq for SpanPosition {\n+    fn eq(&self, other: &Self) -> bool {\n+        self.cmp(other) == Ordering::Equal\n+    }\n+}\n+\n+impl Eq for SpanPosition { }\n+\n+impl PartialOrd for SpanPosition {\n+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {\n+        Some(self.cmp(other))\n+    }\n+}\n+\n+impl Ord for SpanPosition {\n+    fn cmp(&self, other: &Self) -> Ordering {\n+        (self.0).0.cmp(&(other.0).0)\n+    }\n+}\n+\n+/// An iterator specifically for iterating `edn::ValueAndSpan` instances in various ways.\n+///\n+/// Enumerating each iteration type allows us to have a single `combine::Stream` implementation\n+/// yielding `ValueAndSpan` items, which allows us to yield uniform `combine::ParseError` types from\n+/// disparate parsers.\n+#[derive(Clone)]\n+pub enum IntoIter {\n+    Empty(std::iter::Empty<edn::ValueAndSpan>),\n+    Atom(std::iter::Once<edn::ValueAndSpan>),\n+    Vector(std::vec::IntoIter<edn::ValueAndSpan>),\n+    List(std::collections::linked_list::IntoIter<edn::ValueAndSpan>),\n+    /// Iterates via a single `flat_map` [k1, v1, k2, v2, ...].\n+    Map(std::vec::IntoIter<edn::ValueAndSpan>),\n+    // TODO: Support Set and Map more naturally.  This is significantly more work because the\n+    // existing BTreeSet and BTreeMap iterators do not implement Clone, and implementing Clone for\n+    // them is involved.  Since we don't really need to parse sets and maps at this time, this will\n+    // do for now.\n+}\n+\n+impl Iterator for IntoIter {\n+    type Item = edn::ValueAndSpan;\n+\n+    fn next(&mut self) -> Option<Self::Item> {\n+        match *self {\n+            IntoIter::Empty(ref mut i) => i.next(),\n+            IntoIter::Atom(ref mut i) => i.next(),\n+            IntoIter::Vector(ref mut i) => i.next(),\n+            IntoIter::List(ref mut i) => i.next(),\n+            IntoIter::Map(ref mut i) => i.next(),\n+        }\n+    }\n+}\n+\n+/// A single `combine::Stream` implementation iterating `edn::ValueAndSpan` instances.  Equivalent\n+/// to `combine::IteratorStream` as produced by `combine::from_iter`, but specialized to\n+/// `edn::ValueAndSpan`.\n+#[derive(Clone)]\n+pub struct Stream(IntoIter, SpanPosition);\n+\n+/// Things specific to parsing with `combine` and our `Stream` that need a trait to live outside of\n+/// the `edn` crate.\n+pub trait Item: Clone + PartialEq + Sized {\n+    /// Position could be specialized to `SpanPosition`.\n+    type Position: Clone + Ord + std::fmt::Display;\n+\n+    /// A slight generalization of `combine::Positioner` that allows to set the position based on\n+    /// the `edn::ValueAndSpan` being iterated.\n+    fn start(&self) -> Self::Position;\n+    fn update_position(&self, &mut Self::Position);\n+\n+    fn into_child_stream_iter(self) -> IntoIter;\n+    fn into_child_stream(self) -> Stream;\n+    fn into_atom_stream_iter(self) -> IntoIter;\n+    fn into_atom_stream(self) -> Stream;\n+}\n+\n+impl Item for edn::ValueAndSpan {\n+    type Position = SpanPosition;\n+\n+    fn start(&self) -> Self::Position {\n+        SpanPosition(self.span.clone())\n+    }\n+\n+    fn update_position(&self, position: &mut Self::Position) {\n+        *position = SpanPosition(self.span.clone())\n+    }\n+\n+    fn into_child_stream_iter(self) -> IntoIter {\n+        match self.inner {\n+            edn::SpannedValue::Vector(values) => IntoIter::Vector(values.into_iter()),\n+            edn::SpannedValue::List(values) => IntoIter::List(values.into_iter()),\n+            // Parsing pairs with `combine` is tricky; parsing sequences is easy.\n+            edn::SpannedValue::Map(map) => IntoIter::Map(map.into_iter().flat_map(|(a, v)| std::iter::once(a).chain(std::iter::once(v))).collect::<Vec<_>>().into_iter()),","path":"parser-utils/src/value_and_span.rs","position":144,"original_position":137,"commit_id":"7e15d7670abc12add05b80ebf54382fa8db928d3","original_commit_id":"16687259fac5a25c38ff865af03ef0ef08e9d741","user":{"login":"rnewman","id":91722,"avatar_url":"https://avatars1.githubusercontent.com/u/91722?v=3","gravatar_id":"","url":"https://api.github.com/users/rnewman","html_url":"https://github.com/rnewman","followers_url":"https://api.github.com/users/rnewman/followers","following_url":"https://api.github.com/users/rnewman/following{/other_user}","gists_url":"https://api.github.com/users/rnewman/gists{/gist_id}","starred_url":"https://api.github.com/users/rnewman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rnewman/subscriptions","organizations_url":"https://api.github.com/users/rnewman/orgs","repos_url":"https://api.github.com/users/rnewman/repos","events_url":"https://api.github.com/users/rnewman/events{/privacy}","received_events_url":"https://api.github.com/users/rnewman/received_events","type":"User","site_admin":false},"body":"File an issue to improve","created_at":"2017-03-30T23:11:24Z","updated_at":"2017-03-31T00:02:29Z","html_url":"https://github.com/mozilla/mentat/pull/393#discussion_r109059135","pull_request_url":"https://api.github.com/repos/mozilla/mentat/pulls/393","_links":{"self":{"href":"https://api.github.com/repos/mozilla/mentat/pulls/comments/109059135"},"html":{"href":"https://github.com/mozilla/mentat/pull/393#discussion_r109059135"},"pull_request":{"href":"https://api.github.com/repos/mozilla/mentat/pulls/393"}}},"pull_request":{"url":"https://api.github.com/repos/mozilla/mentat/pulls/393","id":113232199,"html_url":"https://github.com/mozilla/mentat/pull/393","diff_url":"https://github.com/mozilla/mentat/pull/393.diff","patch_url":"https://github.com/mozilla/mentat/pull/393.patch","issue_url":"https://api.github.com/repos/mozilla/mentat/issues/393","number":393,"state":"open","locked":false,"title":"Improve parsing of nested `edn::ValueAndSpan` streams","user":{"login":"ncalexan","id":1097182,"avatar_url":"https://avatars3.githubusercontent.com/u/1097182?v=3","gravatar_id":"","url":"https://api.github.com/users/ncalexan","html_url":"https://github.com/ncalexan","followers_url":"https://api.github.com/users/ncalexan/followers","following_url":"https://api.github.com/users/ncalexan/following{/other_user}","gists_url":"https://api.github.com/users/ncalexan/gists{/gist_id}","starred_url":"https://api.github.com/users/ncalexan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ncalexan/subscriptions","organizations_url":"https://api.github.com/users/ncalexan/orgs","repos_url":"https://api.github.com/users/ncalexan/repos","events_url":"https://api.github.com/users/ncalexan/events{/privacy}","received_events_url":"https://api.github.com/users/ncalexan/received_events","type":"User","site_admin":false},"body":"This is work in progress, but you can see how it simplifies a lot of `tx-parser/`.","created_at":"2017-03-29T15:52:53Z","updated_at":"2017-03-31T00:02:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"cc5d1f84e5d6510607bd1046c7f55ec14df1c792","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/mozilla/mentat/pulls/393/commits","review_comments_url":"https://api.github.com/repos/mozilla/mentat/pulls/393/comments","review_comment_url":"https://api.github.com/repos/mozilla/mentat/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mozilla/mentat/issues/393/comments","statuses_url":"https://api.github.com/repos/mozilla/mentat/statuses/7e15d7670abc12add05b80ebf54382fa8db928d3","head":{"label":"ncalexan:nested","ref":"nested","sha":"7e15d7670abc12add05b80ebf54382fa8db928d3","user":{"login":"ncalexan","id":1097182,"avatar_url":"https://avatars3.githubusercontent.com/u/1097182?v=3","gravatar_id":"","url":"https://api.github.com/users/ncalexan","html_url":"https://github.com/ncalexan","followers_url":"https://api.github.com/users/ncalexan/followers","following_url":"https://api.github.com/users/ncalexan/following{/other_user}","gists_url":"https://api.github.com/users/ncalexan/gists{/gist_id}","starred_url":"https://api.github.com/users/ncalexan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ncalexan/subscriptions","organizations_url":"https://api.github.com/users/ncalexan/orgs","repos_url":"https://api.github.com/users/ncalexan/repos","events_url":"https://api.github.com/users/ncalexan/events{/privacy}","received_events_url":"https://api.github.com/users/ncalexan/received_events","type":"User","site_admin":false},"repo":{"id":70625837,"name":"mentat","full_name":"ncalexan/mentat","owner":{"login":"ncalexan","id":1097182,"avatar_url":"https://avatars3.githubusercontent.com/u/1097182?v=3","gravatar_id":"","url":"https://api.github.com/users/ncalexan","html_url":"https://github.com/ncalexan","followers_url":"https://api.github.com/users/ncalexan/followers","following_url":"https://api.github.com/users/ncalexan/following{/other_user}","gists_url":"https://api.github.com/users/ncalexan/gists{/gist_id}","starred_url":"https://api.github.com/users/ncalexan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ncalexan/subscriptions","organizations_url":"https://api.github.com/users/ncalexan/orgs","repos_url":"https://api.github.com/users/ncalexan/repos","events_url":"https://api.github.com/users/ncalexan/events{/privacy}","received_events_url":"https://api.github.com/users/ncalexan/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ncalexan/mentat","description":"A persistent, relational store inspired by Datomic and DataScript.","fork":true,"url":"https://api.github.com/repos/ncalexan/mentat","forks_url":"https://api.github.com/repos/ncalexan/mentat/forks","keys_url":"https://api.github.com/repos/ncalexan/mentat/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ncalexan/mentat/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ncalexan/mentat/teams","hooks_url":"https://api.github.com/repos/ncalexan/mentat/hooks","issue_events_url":"https://api.github.com/repos/ncalexan/mentat/issues/events{/number}","events_url":"https://api.github.com/repos/ncalexan/mentat/events","assignees_url":"https://api.github.com/repos/ncalexan/mentat/assignees{/user}","branches_url":"https://api.github.com/repos/ncalexan/mentat/branches{/branch}","tags_url":"https://api.github.com/repos/ncalexan/mentat/tags","blobs_url":"https://api.github.com/repos/ncalexan/mentat/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ncalexan/mentat/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ncalexan/mentat/git/refs{/sha}","trees_url":"https://api.github.com/repos/ncalexan/mentat/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ncalexan/mentat/statuses/{sha}","languages_url":"https://api.github.com/repos/ncalexan/mentat/languages","stargazers_url":"https://api.github.com/repos/ncalexan/mentat/stargazers","contributors_url":"https://api.github.com/repos/ncalexan/mentat/contributors","subscribers_url":"https://api.github.com/repos/ncalexan/mentat/subscribers","subscription_url":"https://api.github.com/repos/ncalexan/mentat/subscription","commits_url":"https://api.github.com/repos/ncalexan/mentat/commits{/sha}","git_commits_url":"https://api.github.com/repos/ncalexan/mentat/git/commits{/sha}","comments_url":"https://api.github.com/repos/ncalexan/mentat/comments{/number}","issue_comment_url":"https://api.github.com/repos/ncalexan/mentat/issues/comments{/number}","contents_url":"https://api.github.com/repos/ncalexan/mentat/contents/{+path}","compare_url":"https://api.github.com/repos/ncalexan/mentat/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ncalexan/mentat/merges","archive_url":"https://api.github.com/repos/ncalexan/mentat/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ncalexan/mentat/downloads","issues_url":"https://api.github.com/repos/ncalexan/mentat/issues{/number}","pulls_url":"https://api.github.com/repos/ncalexan/mentat/pulls{/number}","milestones_url":"https://api.github.com/repos/ncalexan/mentat/milestones{/number}","notifications_url":"https://api.github.com/repos/ncalexan/mentat/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ncalexan/mentat/labels{/name}","releases_url":"https://api.github.com/repos/ncalexan/mentat/releases{/id}","deployments_url":"https://api.github.com/repos/ncalexan/mentat/deployments","created_at":"2016-10-11T18:58:08Z","updated_at":"2017-01-11T22:55:06Z","pushed_at":"2017-03-30T22:32:44Z","git_url":"git://github.com/ncalexan/mentat.git","ssh_url":"git@github.com:ncalexan/mentat.git","clone_url":"https://github.com/ncalexan/mentat.git","svn_url":"https://github.com/ncalexan/mentat","homepage":null,"size":1257,"stargazers_count":0,"watchers_count":0,"language":"Clojure","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"mozilla:rust","ref":"rust","sha":"8e6f37e709cf25e3fc2c88ca946743a1f210a450","user":{"login":"mozilla","id":131524,"avatar_url":"https://avatars1.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"repo":{"id":62660036,"name":"mentat","full_name":"mozilla/mentat","owner":{"login":"mozilla","id":131524,"avatar_url":"https://avatars1.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mozilla/mentat","description":"A persistent, relational store inspired by Datomic and DataScript.","fork":false,"url":"https://api.github.com/repos/mozilla/mentat","forks_url":"https://api.github.com/repos/mozilla/mentat/forks","keys_url":"https://api.github.com/repos/mozilla/mentat/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mozilla/mentat/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mozilla/mentat/teams","hooks_url":"https://api.github.com/repos/mozilla/mentat/hooks","issue_events_url":"https://api.github.com/repos/mozilla/mentat/issues/events{/number}","events_url":"https://api.github.com/repos/mozilla/mentat/events","assignees_url":"https://api.github.com/repos/mozilla/mentat/assignees{/user}","branches_url":"https://api.github.com/repos/mozilla/mentat/branches{/branch}","tags_url":"https://api.github.com/repos/mozilla/mentat/tags","blobs_url":"https://api.github.com/repos/mozilla/mentat/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mozilla/mentat/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mozilla/mentat/git/refs{/sha}","trees_url":"https://api.github.com/repos/mozilla/mentat/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mozilla/mentat/statuses/{sha}","languages_url":"https://api.github.com/repos/mozilla/mentat/languages","stargazers_url":"https://api.github.com/repos/mozilla/mentat/stargazers","contributors_url":"https://api.github.com/repos/mozilla/mentat/contributors","subscribers_url":"https://api.github.com/repos/mozilla/mentat/subscribers","subscription_url":"https://api.github.com/repos/mozilla/mentat/subscription","commits_url":"https://api.github.com/repos/mozilla/mentat/commits{/sha}","git_commits_url":"https://api.github.com/repos/mozilla/mentat/git/commits{/sha}","comments_url":"https://api.github.com/repos/mozilla/mentat/comments{/number}","issue_comment_url":"https://api.github.com/repos/mozilla/mentat/issues/comments{/number}","contents_url":"https://api.github.com/repos/mozilla/mentat/contents/{+path}","compare_url":"https://api.github.com/repos/mozilla/mentat/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mozilla/mentat/merges","archive_url":"https://api.github.com/repos/mozilla/mentat/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mozilla/mentat/downloads","issues_url":"https://api.github.com/repos/mozilla/mentat/issues{/number}","pulls_url":"https://api.github.com/repos/mozilla/mentat/pulls{/number}","milestones_url":"https://api.github.com/repos/mozilla/mentat/milestones{/number}","notifications_url":"https://api.github.com/repos/mozilla/mentat/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mozilla/mentat/labels{/name}","releases_url":"https://api.github.com/repos/mozilla/mentat/releases{/id}","deployments_url":"https://api.github.com/repos/mozilla/mentat/deployments","created_at":"2016-07-05T18:29:34Z","updated_at":"2017-03-28T23:46:13Z","pushed_at":"2017-03-30T22:32:45Z","git_url":"git://github.com/mozilla/mentat.git","ssh_url":"git@github.com:mozilla/mentat.git","clone_url":"https://github.com/mozilla/mentat.git","svn_url":"https://github.com/mozilla/mentat","homepage":null,"size":1144,"stargazers_count":653,"watchers_count":653,"language":"Rust","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":18,"mirror_url":null,"open_issues_count":149,"forks":18,"open_issues":149,"watchers":653,"default_branch":"rust"}},"_links":{"self":{"href":"https://api.github.com/repos/mozilla/mentat/pulls/393"},"html":{"href":"https://github.com/mozilla/mentat/pull/393"},"issue":{"href":"https://api.github.com/repos/mozilla/mentat/issues/393"},"comments":{"href":"https://api.github.com/repos/mozilla/mentat/issues/393/comments"},"review_comments":{"href":"https://api.github.com/repos/mozilla/mentat/pulls/393/comments"},"review_comment":{"href":"https://api.github.com/repos/mozilla/mentat/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mozilla/mentat/pulls/393/commits"},"statuses":{"href":"https://api.github.com/repos/mozilla/mentat/statuses/7e15d7670abc12add05b80ebf54382fa8db928d3"}}}}
{"actor":{"display_login":"rnewman"}}