2014-12-08 17:29:40 +01:00
|
|
|
package docs.stream.cookbook
|
|
|
|
|
|
|
|
|
|
import scala.concurrent.Await
|
|
|
|
|
import scala.concurrent.duration._
|
|
|
|
|
|
|
|
|
|
class RecipeDigest extends RecipeSpec {
|
|
|
|
|
|
|
|
|
|
"Recipe for calculating digest" must {
|
|
|
|
|
|
|
|
|
|
"work" in {
|
|
|
|
|
|
|
|
|
|
//#calculating-digest
|
2018-03-03 08:22:46 +01:00
|
|
|
import java.security.MessageDigest
|
|
|
|
|
|
|
|
|
|
import akka.NotUsed
|
|
|
|
|
import akka.stream.{ Attributes, Outlet, Inlet, FlowShape }
|
|
|
|
|
import akka.stream.scaladsl.{ Sink, Source }
|
|
|
|
|
import akka.util.ByteString
|
|
|
|
|
|
2014-12-08 17:29:40 +01:00
|
|
|
import akka.stream.stage._
|
2018-03-03 08:22:46 +01:00
|
|
|
|
|
|
|
|
val data: Source[ByteString, NotUsed] = Source.single(ByteString("abc"))
|
|
|
|
|
|
2016-02-11 16:39:25 +01:00
|
|
|
class DigestCalculator(algorithm: String) extends GraphStage[FlowShape[ByteString, ByteString]] {
|
|
|
|
|
val in = Inlet[ByteString]("DigestCalculator.in")
|
|
|
|
|
val out = Outlet[ByteString]("DigestCalculator.out")
|
2018-03-03 08:22:46 +01:00
|
|
|
override val shape = FlowShape(in, out)
|
2016-02-11 16:39:25 +01:00
|
|
|
|
|
|
|
|
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) {
|
2018-03-03 08:22:46 +01:00
|
|
|
private val digest = MessageDigest.getInstance(algorithm)
|
2016-02-11 16:39:25 +01:00
|
|
|
|
|
|
|
|
setHandler(out, new OutHandler {
|
2018-03-03 08:22:46 +01:00
|
|
|
override def onPull(): Unit = pull(in)
|
2016-02-11 16:39:25 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
setHandler(in, new InHandler {
|
2018-03-03 08:22:46 +01:00
|
|
|
override def onPush(): Unit = {
|
2016-02-11 16:39:25 +01:00
|
|
|
val chunk = grab(in)
|
|
|
|
|
digest.update(chunk.toArray)
|
|
|
|
|
pull(in)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override def onUpstreamFinish(): Unit = {
|
|
|
|
|
emit(out, ByteString(digest.digest()))
|
|
|
|
|
completeStage()
|
|
|
|
|
}
|
|
|
|
|
})
|
2014-12-08 17:29:40 +01:00
|
|
|
}
|
|
|
|
|
}
|
2018-03-03 08:22:46 +01:00
|
|
|
|
2016-02-11 16:39:25 +01:00
|
|
|
val digest: Source[ByteString, NotUsed] = data.via(new DigestCalculator("SHA-256"))
|
2014-12-08 17:29:40 +01:00
|
|
|
//#calculating-digest
|
|
|
|
|
|
2015-03-05 12:21:17 +01:00
|
|
|
Await.result(digest.runWith(Sink.head), 3.seconds) should be(
|
2014-12-08 17:29:40 +01:00
|
|
|
ByteString(
|
2018-03-03 08:22:46 +01:00
|
|
|
0xba, 0x78, 0x16, 0xbf,
|
|
|
|
|
0x8f, 0x01, 0xcf, 0xea,
|
|
|
|
|
0x41, 0x41, 0x40, 0xde,
|
|
|
|
|
0x5d, 0xae, 0x22, 0x23,
|
|
|
|
|
0xb0, 0x03, 0x61, 0xa3,
|
|
|
|
|
0x96, 0x17, 0x7a, 0x9c,
|
|
|
|
|
0xb4, 0x10, 0xff, 0x61,
|
|
|
|
|
0xf2, 0x00, 0x15, 0xad))
|
2014-12-08 17:29:40 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|