Skip to content

Commit

Permalink
Add module that uses snakeyaml-engine, which only handles yaml 1.2 (#303
Browse files Browse the repository at this point in the history
)

closes #300
closes #301
closes #302
  • Loading branch information
sideeffffect committed Nov 14, 2022
1 parent 9df6d5c commit d3d0907
Show file tree
Hide file tree
Showing 50 changed files with 1,206 additions and 63 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
build:
name: Build and Test
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
scala: [2.12.15, 2.13.8, 3.2.0]
Expand Down
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
[![Codecov status](https://codecov.io/gh/circe/circe-yaml/branch/master/graph/badge.svg)](https://codecov.io/gh/circe/circe-yaml)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.circe/circe-yaml_2.12/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.circe/circe-yaml_2.12)

This is a small library which translates [SnakeYAML](https://bitbucket.org/snakeyaml/snakeyaml)'s AST into
[circe](https://github.com/circe/circe)'s AST. It enables parsing [YAML](https://yaml.org) 1.1 documents into circe's
`Json` AST.
This is a small library for parsing [YAML](https://yaml.org) into [circe](https://github.com/circe/circe)'s `Json` AST.
* For parsing YAML 1.1 it uses [SnakeYAML](https://bitbucket.org/snakeyaml/snakeyaml).
* For parsing YAML 1.2 it uses [snakeyaml-engine](https://bitbucket.org/snakeyaml/snakeyaml-engine).

## Why?

Expand All @@ -22,14 +22,19 @@ the ADT marshalling. You can also use circe's `Encoder` to obtain a `Json`, and

The artifact is hosted by Sonatype, and release versions are synced to Maven Central:

For YAML 1.1
```scala
libraryDependencies += "io.circe" %% "circe-yaml" % "0.14.1"
libraryDependencies += "io.circe" %% "circe-yaml" % "0.14.2"
```
or for YAML 1.2
```scala
libraryDependencies += "io.circe" %% "circe-yaml-v12" % "0.14.2"
```

Snapshot versions are available by adding the Sonatype Snapshots resolver:

```scala
resolvers += Resolver.sonatypeRepo("snapshots")
resolvers ++= Resolver.sonatypeOssRepos("snapshots")
```

### Parsing
Expand Down
122 changes: 86 additions & 36 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ val Versions = new {
val scalaTest = "3.2.14"
val scalaTestPlus = "3.2.11.0"
val snakeYaml = "1.33"
val snakeYamlEngine = "2.5"
val previousCirceYamls = Set("0.14.0", "0.14.1", "0.14.2")
}

Expand All @@ -28,44 +29,92 @@ ThisBuild / crossScalaVersions := Seq("2.12.15", "2.13.8", "3.2.0")

val root = project
.in(file("."))
.enablePlugins(GhpagesPlugin)
// .settings(commonSettings)
.settings(
name := "circe-yaml",
description := "Library for converting between SnakeYAML's AST and circe's AST",
scalacOptions ++= compilerOptions,
scalacOptions ++= {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, v)) if v <= 12 =>
Seq(
"-Xfuture",
"-Yno-adapted-args",
"-Ywarn-unused-import"
)
case _ =>
Seq(
"-Ywarn-unused:imports"
)
}
},
Compile / console / scalacOptions ~= {
_.filterNot(Set("-Ywarn-unused-import", "-Ywarn-unused:imports"))
},
Test / console / scalacOptions ~= {
_.filterNot(Set("-Ywarn-unused-import", "-Ywarn-unused:imports"))
},
libraryDependencies ++= Seq(
"io.circe" %% "circe-core" % Versions.circe,
"io.circe" %% "circe-jawn" % Versions.circe % Test,
"org.yaml" % "snakeyaml" % Versions.snakeYaml,
"io.circe" %% "circe-testing" % Versions.circe % Test,
"org.typelevel" %% "discipline-core" % Versions.discipline % Test,
"org.scalacheck" %% "scalacheck" % Versions.scalaCheck % Test,
"org.scalatest" %% "scalatest" % Versions.scalaTest % Test,
"org.scalatestplus" %% "scalacheck-1-15" % Versions.scalaTestPlus % Test
),
mimaPreviousArtifacts := Versions.previousCirceYamls.map("io.circe" %% "circe-yaml" % _)
name := "circe-yaml-root",
publish / skip := true
)
.aggregate(
`circe-yaml-common`,
`circe-yaml`,
`circe-yaml-v12`
)
.settings(publishSettings ++ docSettings)
// .enablePlugins(GhpagesPlugin)

lazy val `circe-yaml-common` =
project
.in(file("circe-yaml-common"))
.settings(commonSettings)
.settings(
description := "Library for converting between SnakeYAML's AST (YAML 1.1) and circe's AST",
libraryDependencies ++= Seq(
"io.circe" %% "circe-core" % Versions.circe
)
)
.enablePlugins(GhpagesPlugin)

lazy val `circe-yaml` =
project
.in(file("circe-yaml"))
.settings(commonSettings)
.dependsOn(`circe-yaml-common`)
.settings(
description := "Library for converting between SnakeYAML's AST (YAML 1.1) and circe's AST",
libraryDependencies ++= Seq(
"org.yaml" % "snakeyaml" % Versions.snakeYaml,
"io.circe" %% "circe-jawn" % Versions.circe % Test,
"io.circe" %% "circe-testing" % Versions.circe % Test,
"org.typelevel" %% "discipline-core" % Versions.discipline % Test,
"org.scalacheck" %% "scalacheck" % Versions.scalaCheck % Test,
"org.scalatest" %% "scalatest" % Versions.scalaTest % Test,
"org.scalatestplus" %% "scalacheck-1-15" % Versions.scalaTestPlus % Test
),
mimaPreviousArtifacts := Versions.previousCirceYamls.map("io.circe" %% "circe-yaml" % _)
)
.enablePlugins(GhpagesPlugin)

lazy val `circe-yaml-v12` =
project
.in(file("circe-yaml-v12"))
.settings(commonSettings)
.dependsOn(`circe-yaml-common`)
.settings(
description := "Library for converting between snakeyaml-engine's AST (YAML 1.2) and circe's AST",
libraryDependencies ++= Seq(
"io.circe" %% "circe-jawn" % Versions.circe % Test,
"org.snakeyaml" % "snakeyaml-engine" % Versions.snakeYamlEngine,
"io.circe" %% "circe-testing" % Versions.circe % Test,
"org.typelevel" %% "discipline-core" % Versions.discipline % Test,
"org.scalacheck" %% "scalacheck" % Versions.scalaCheck % Test,
"org.scalatest" %% "scalatest" % Versions.scalaTest % Test,
"org.scalatestplus" %% "scalacheck-1-15" % Versions.scalaTestPlus % Test
)
)
.enablePlugins(GhpagesPlugin)

lazy val commonSettings = List(
scalacOptions ++= compilerOptions,
scalacOptions ++= {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, v)) if v <= 12 =>
Seq(
"-Xfuture",
"-Yno-adapted-args",
"-Ywarn-unused-import"
)
case _ =>
Seq(
"-Ywarn-unused:imports"
)
}
},
Compile / console / scalacOptions ~= {
_.filterNot(Set("-Ywarn-unused-import", "-Ywarn-unused:imports"))
},
Test / console / scalacOptions ~= {
_.filterNot(Set("-Ywarn-unused-import", "-Ywarn-unused:imports"))
}
) ++ publishSettings ++ docSettings

lazy val docSettings = Seq(
autoAPIMappings := true,
Expand Down Expand Up @@ -116,6 +165,7 @@ lazy val publishSettings = Seq(
ThisBuild / githubWorkflowJavaVersions := Seq("adopt@1.8")
// No auto-publish atm. Remove this line to generate publish stage
ThisBuild / githubWorkflowPublishTargetBranches := Seq.empty
ThisBuild / githubWorkflowBuildMatrixFailFast := Some(false)
ThisBuild / githubWorkflowBuild := Seq(
WorkflowStep.Sbt(
List("clean", "coverage", "test", "coverageReport", "scalastyle", "scalafmtCheckAll"),
Expand Down
20 changes: 20 additions & 0 deletions circe-yaml-common/src/main/scala/io/circe/yaml/common/Parser.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.circe.yaml.common

import cats.data.ValidatedNel
import io.circe.{ Decoder, Error, Json, ParsingFailure }
import java.io.Reader

trait Parser extends io.circe.Parser {

/**
* Parse YAML from the given [[Reader]], returning either [[ParsingFailure]] or [[Json]]
*
* @param yaml
* @return
*/
def parse(yaml: Reader): Either[ParsingFailure, Json]
def parseDocuments(yaml: Reader): Stream[Either[ParsingFailure, Json]]
def parseDocuments(yaml: String): Stream[Either[ParsingFailure, Json]]
def decode[A: Decoder](input: Reader): Either[Error, A]
def decodeAccumulating[A: Decoder](input: Reader): ValidatedNel[Error, A]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.circe.yaml.common

import io.circe.Json

trait Printer {
def pretty(json: Json): String
}

object Printer {

sealed trait FlowStyle
object FlowStyle {
case object Flow extends FlowStyle
case object Block extends FlowStyle
}

sealed trait LineBreak
object LineBreak {
case object Unix extends LineBreak
case object Windows extends LineBreak
case object Mac extends LineBreak
}

sealed trait StringStyle
object StringStyle {
case object Plain extends StringStyle
case object DoubleQuoted extends StringStyle
case object SingleQuoted extends StringStyle
case object Literal extends StringStyle
case object Folded extends StringStyle
}

}
33 changes: 33 additions & 0 deletions circe-yaml-v12/src/main/scala/io/circe/yaml/v12/Parser.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.circe.yaml.v12

import io.circe.yaml.common
import org.snakeyaml.engine.v2.api.LoadSettings

object Parser {
final case class Config(
allowDuplicateKeys: Boolean = false,
allowRecursiveKeys: Boolean = false,
bufferSize: Int = 1024,
label: String = "reader",
maxAliasesForCollections: Int = 50,
parseComments: Boolean = false,
useMarks: Boolean = true
)

def make(config: Config = Config()): common.Parser = {
import config._
new ParserImpl(
LoadSettings.builder
.setAllowDuplicateKeys(allowDuplicateKeys)
.setAllowRecursiveKeys(allowRecursiveKeys)
.setBufferSize(bufferSize)
.setLabel(label)
.setMaxAliasesForCollections(maxAliasesForCollections)
.setParseComments(parseComments)
.setUseMarks(useMarks)
.build
)
}

lazy val default: common.Parser = make()
}
Loading

0 comments on commit d3d0907

Please sign in to comment.