Skip to content

Commit a6f9979

Browse files
committed
add test for asMany
1 parent 91e5c6e commit a6f9979

File tree

2 files changed

+66
-7
lines changed

2 files changed

+66
-7
lines changed

core/shared/src/main/scala/org/virtuslab/yaml/Yaml.scala

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import org.virtuslab.yaml.internal.load.compose.ComposerImpl
66
import org.virtuslab.yaml.internal.load.parse.Parser
77
import org.virtuslab.yaml.internal.load.parse.ParserImpl
88
import org.virtuslab.yaml.internal.load.reader.Tokenizer
9+
import scala.annotation.tailrec
910

1011
package object yaml {
1112

@@ -35,13 +36,13 @@ package object yaml {
3536
implicit class StringOps(val str: String) extends AnyVal {
3637

3738
/**
38-
* Parse YAML from the given [[String]], returning either [[YamlError]] or [[T]].
39-
*
40-
* According to the specification:
41-
* - [[Parser]] takes input string and produces sequence of events
42-
* - then [[Composer]] produces a representation graph from events
43-
* - finally [[YamlDecoder]] (construct phase from the YAML spec) constructs data type [[T]] from the YAML representation.
44-
*/
39+
* Parse YAML from the given [[String]], returning either [[YamlError]] or [[T]].
40+
*
41+
* According to the specification:
42+
* - [[Parser]] takes input string and produces sequence of events
43+
* - then [[Composer]] produces a representation graph from events
44+
* - finally [[YamlDecoder]] (construct phase from the YAML spec) constructs data type [[T]] from the YAML representation.
45+
*/
4546
def as[T](implicit
4647
c: YamlDecoder[T],
4748
settings: LoadSettings = LoadSettings.empty
@@ -51,6 +52,29 @@ package object yaml {
5152
t <- node.as[T]
5253
} yield t
5354

55+
/**
56+
* Parse YAML from the given [[String]], returning either [[YamlError]] or a list of [[T]].
57+
* The error will be the first failure in parsing or converting to [[T]].
58+
*/
59+
def asMany[T](implicit
60+
c: YamlDecoder[T],
61+
settings: LoadSettings = LoadSettings.empty
62+
): Either[YamlError, List[T]] =
63+
parseAllYamls(str).flatMap { nodes =>
64+
@tailrec
65+
def parseNodes(n: List[Node], out: List[T]): Either[YamlError, List[T]] =
66+
n match {
67+
case Nil => Right(out.reverse)
68+
case head :: tail =>
69+
head.as[T] match {
70+
case Left(error) => Left(error)
71+
case Right(value) => parseNodes(tail, value :: out)
72+
}
73+
}
74+
75+
parseNodes(nodes, Nil)
76+
}
77+
5478
def asNode: Either[YamlError, Node] = parseYaml(str)
5579
}
5680

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.virtuslab.yaml
2+
3+
class YamlPackageSuite extends BaseYamlSuite {
4+
test("asMany fails on parse failure") {
5+
val yaml = "["
6+
val actual = yaml.asMany[Int]
7+
assert(actual.isLeft)
8+
}
9+
10+
test("asMany fails on first decoder failure") {
11+
val yaml = """
12+
|123
13+
|---
14+
|not an Int
15+
|""".stripMargin
16+
17+
val actual = yaml.asMany[Int]
18+
assert(actual.isLeft)
19+
val errorMessage = actual.left.get.getMessage()
20+
assert(errorMessage.contains("not an Int"))
21+
}
22+
23+
test("asMany succeeds with multiple valid documents") {
24+
val yaml = """
25+
|123
26+
|---
27+
|42
28+
|""".stripMargin
29+
30+
val actual = yaml.asMany[Int]
31+
assert(actual.isRight)
32+
val ints = actual.right.get
33+
assertEquals(ints, List(123, 42))
34+
}
35+
}

0 commit comments

Comments
 (0)