Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fastparse implementation #1

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Fastparse implementation #1

wants to merge 2 commits into from

Conversation

aborg0
Copy link
Owner

@aborg0 aborg0 commented Jun 14, 2018

Below is the output of the updated tut/Examples.md output (check the second part!):

Examples

Intro

There might be multiple implementations of ParseCaseClass, currently only RegexParseCaseClass and FastParseParseCaseClass are supported, but only one should be used in a scope (in this case RegexParseCaseClass):

import com.github.aborg0.caseyclassy.RegexParseCaseClass
import com.github.aborg0.caseyclassy.RegexParseCaseClass._
import java.time.{LocalDate, LocalTime}
import shapeless._

It is possible to parse simple values, like Boolean, Byte, Short, Int, Long, Float, Double, LocalTime, LocalDate and Strings without comma (,) or closing parenthesis ()), but this library was designed to parse toString of algebraic data types (products -case classes, tuples- and coproducts) of them. Also some Seqs (List, Vector, WrappedArray (for varargs)) are supported.

Simple primitives

LocalDate:

scala> val date: LocalDate = RegexParseCaseClass.to[LocalDate]("2018-04-01")
date: java.time.LocalDate = 2018-04-01

or it is also possible to create a parser and reuse it:

scala> val dateParser = RegexParseCaseClass[LocalDate]
dateParser: com.github.aborg0.caseyclassy.RegexParse[java.time.LocalDate] = com.github.aborg0.caseyclassy.RegexParseCaseClass$$anon$11@602995d3

scala> dateParser.parse("2018-04-01")
res0: java.time.LocalDate = 2018-04-01

scala> dateParser.parse("2018-04-22")
res1: java.time.LocalDate = 2018-04-22

Tuple2 of String and Int:

scala> RegexParseCaseClass.to[(String, Int)]("(   hello,4)")
res2: (String, Int) = ("   hello",4)

Or in the other order:

scala> val (i, s) = RegexParseCaseClass.to[(Int, String)]("(4,   hello)")
i: Int = 4
s: String = "   hello"

The error messages are not very good:

scala> val dateTuple1 = RegexParseCaseClass.to[Tuple1[LocalDate]]("2018-04-01")
java.lang.IllegalArgumentException: |018-04-0| does not start with proper value
  at com.github.aborg0.caseyclassy.CommonRegexParse.$anonfun$parse$6(RegexParseCaseClass.scala:183)
  at scala.Option.getOrElse(Option.scala:121)
  at com.github.aborg0.caseyclassy.CommonRegexParse.parse(RegexParseCaseClass.scala:183)
  at com.github.aborg0.caseyclassy.CommonRegexParse.parse$(RegexParseCaseClass.scala:182)
  at com.github.aborg0.caseyclassy.RegexParseCaseClass$$anon$11.parse(RegexParseCaseClass.scala:145)
  at com.github.aborg0.caseyclassy.GenericImplementations$$anon$2.parse(RegexParseCaseClass.scala:62)
  at com.github.aborg0.caseyclassy.GenericImplementations$$anon$2.parse(RegexParseCaseClass.scala:51)
  at com.github.aborg0.caseyclassy.GenericImplementations$$anon$4.parse(RegexParseCaseClass.scala:114)
  at com.github.aborg0.caseyclassy.RegexParseCaseClass$.to(RegexParseCaseClass.scala:130)
  ... 43 elided

Algebraic data types

With help of shapeless the following constructs are supported:

  • case classes
  • case objects
  • sealed hierarchies
  • tuples
  • a few Seq types

Case classes

scala> case class Example(a: Int, s: String)
defined class Example

scala> RegexParseCaseClass.to[Example]("Example(-3, Hello)")
res3: Example = Example(-3, Hello)
scala> case object Dot
defined object Dot

scala> RegexParseCaseClass.to[Dot.type]("Dot")
res4: Dot.type = Dot

Sealed hierarchies

Either

scala> RegexParseCaseClass.to[Either[Short, Boolean]]("Left(-1111)")
res5: Either[Short,Boolean] = Left(-1111)

scala> RegexParseCaseClass.to[Either[Short, Boolean]]("Right(false)")
res6: Either[Short,Boolean] = Right(false)

Option

scala> RegexParseCaseClass.to[Option[Option[Int]]]("Some(None)")
res7: Option[Option[Int]] = Some(None)

scala> RegexParseCaseClass.to[Option[Option[Int]]]("None")
res8: Option[Option[Int]] = None

scala> RegexParseCaseClass.to[Option[Either[String, Seq[Boolean]]]]("Some(Right(List()))")
res9: Option[Either[String,Seq[Boolean]]] = Some(Right(Vector()))

scala> RegexParseCaseClass.to[Option[Either[String, Seq[Boolean]]]]("Some(Right(List(false, true)))")
res10: Option[Either[String,Seq[Boolean]]] = Some(Right(Vector(false, true)))

Limitations

String handling is not ideal:

scala> RegexParseCaseClass.to[Option[Either[String, Seq[Boolean]]]]("Some(Left(List(false, true)))")
res11: Option[Either[String,Seq[Boolean]]] = Some(Left(List(false))

Please note that the String part contains only till the first , (List(false) within and no error is reported currently.

Same content with FastParse (FastParseParseCaseClass)

Intro

There might be multiple implementations of ParseCaseClass, currently only RegexParseCaseClass and FastParseParseCaseClass are supported, but only one should be used in a scope (in this case FastParseParseCaseClass):

import com.github.aborg0.caseyclassy.FastParseParseCaseClass
import com.github.aborg0.caseyclassy.FastParseParseCaseClass._
import java.time.{LocalDate, LocalTime}
import shapeless._

It is possible to parse simple values, like Boolean, Byte, Short, Int, Long, Float, Double, LocalTime, LocalDate and Strings without comma (,) or closing parenthesis ()), but this library was designed to parse toString of algebraic data types (products -case classes, tuples- and coproducts) of them. Also some Seqs (List, Vector, WrappedArray (for varargs)) are supported.

Simple primitives

LocalDate:

scala> val date: LocalDate = FastParseParseCaseClass.to[LocalDate]("2018-04-01")
date: java.time.LocalDate = 2018-04-01

or it is also possible to create a parser and reuse it:

scala> val dateParser = FastParseParseCaseClass[LocalDate]
dateParser: com.github.aborg0.caseyclassy.FastParseParse[java.time.LocalDate] = com.github.aborg0.caseyclassy.FastParseParseCaseClass$$anonfun$dateParse$4@66ec5b45

scala> dateParser.parse("2018-04-01")
res0: java.time.LocalDate = 2018-04-01

scala> dateParser.parse("2018-04-22")
res1: java.time.LocalDate = 2018-04-22

Tuple2 of String and Int:

scala> FastParseParseCaseClass.to[(String, Int)]("(   hello,4)")
res2: (String, Int) = ("   hello",4)

Or in the other order:

scala> val (i, s) = FastParseParseCaseClass.to[(Int, String)]("(4,   hello)")
i: Int = 4
s: String = "   hello"

The error messages are not very good:

scala> val dateTuple1 = FastParseParseCaseClass.to[Tuple1[LocalDate]]("2018-04-01")
java.lang.IllegalArgumentException: Expected: "(" at position: 0
  at com.github.aborg0.caseyclassy.FastParseParse.$anonfun$parse$1(FastParseParseCaseClass.scala:88)
  at com.github.aborg0.caseyclassy.FastParseParse.$anonfun$parse$1$adapted(FastParseParseCaseClass.scala:87)
  at fastparse.core.Parsed.fold(Parsing.scala:40)
  at fastparse.core.Parsed.fold$(Parsing.scala:38)
  at fastparse.core.Parsed$Failure.fold(Parsing.scala:74)
  at com.github.aborg0.caseyclassy.FastParseParse.parse(FastParseParseCaseClass.scala:88)
  at com.github.aborg0.caseyclassy.FastParseParse.parse$(FastParseParseCaseClass.scala:87)
  at com.github.aborg0.caseyclassy.FPGenericImplementations$$anonfun$generic$10.parse(FastParseParseCaseClass.scala:44)
  at com.github.aborg0.caseyclassy.FastParseParseCaseClass$.to(FastParseParseCaseClass.scala:59)
  ... 43 elided

Algebraic data types

With help of shapeless the following constructs are supported:

  • case classes
  • case objects
  • sealed hierarchies
  • tuples
  • a few Seq types

Case classes

scala> case class Example(a: Int, s: String)
defined class Example

scala> FastParseParseCaseClass.to[Example]("Example(-3, Hello)")
res3: Example = Example(-3, Hello)
scala> case object Dot
defined object Dot

scala> FastParseParseCaseClass.to[Dot.type]("Dot")
res4: Dot.type = Dot

Sealed hierarchies

Either

scala> FastParseParseCaseClass.to[Either[Short, Boolean]]("Left(-1111)")
res5: Either[Short,Boolean] = Left(-1111)

scala> FastParseParseCaseClass.to[Either[Short, Boolean]]("Right(false)")
res6: Either[Short,Boolean] = Right(false)

Option

scala> FastParseParseCaseClass.to[Option[Option[Int]]]("Some(None)")
res7: Option[Option[Int]] = Some(None)

scala> FastParseParseCaseClass.to[Option[Option[Int]]]("None")
res8: Option[Option[Int]] = None

scala> FastParseParseCaseClass.to[Option[Either[String, Seq[Boolean]]]]("Some(Right(List()))")
res9: Option[Either[String,Seq[Boolean]]] = Some(Right(ArrayBuffer()))

scala> FastParseParseCaseClass.to[Option[Either[String, Seq[Boolean]]]]("Some(Right(List(false, true)))")
res10: Option[Either[String,Seq[Boolean]]] = Some(Right(ArrayBuffer(false, true)))

@coveralls
Copy link

Pull Request Test Coverage Report for Build 26

  • 35 of 36 (97.22%) changed or added relevant lines in 1 file are covered.
  • 1 unchanged line in 1 file lost coverage.
  • Overall coverage decreased (-0.2%) to 94.872%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/main/scala/com/github/aborg0/caseyclassy/FastParseParseCaseClass.scala 35 36 97.22%
Files with Coverage Reduction New Missed Lines %
src/main/scala/com/github/aborg0/caseyclassy/RegexParseCaseClass.scala 1 93.83%
Totals Coverage Status
Change from base Build 22: -0.2%
Covered Lines: 111
Relevant Lines: 117

💛 - Coveralls

1 similar comment
@coveralls
Copy link

Pull Request Test Coverage Report for Build 26

  • 35 of 36 (97.22%) changed or added relevant lines in 1 file are covered.
  • 1 unchanged line in 1 file lost coverage.
  • Overall coverage decreased (-0.2%) to 94.872%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/main/scala/com/github/aborg0/caseyclassy/FastParseParseCaseClass.scala 35 36 97.22%
Files with Coverage Reduction New Missed Lines %
src/main/scala/com/github/aborg0/caseyclassy/RegexParseCaseClass.scala 1 93.83%
Totals Coverage Status
Change from base Build 22: -0.2%
Covered Lines: 111
Relevant Lines: 117

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants