Background
I am using Akka Streams and I want to add some extension methods to Flow[In, Out, Mat]
which are specifically for when Out
is a Seq
.
I am starting with this trait to make it easy to get at the type fields:
trait StageOps[+Out, +Mat] {
protected val stage: FlowOps[Out, Mat]
type Repr[+O] = stage.Repr[O]
type Closed = stage.Closed
}
Then I have this (more details to follow later):
trait FramingOps[Out <: Seq[_], Mat] extends StageOps[Out, Mat] {
def frame(start: Out, end: Out): Repr[Out] = {
...
}
}
And now the implicit conversion:
implicit class SeqFlowOps[In, Out <: Seq[_], Mat](val stage: Flow[In, Out, Mat])
extends FramingOps[Out, Mat] {}
This worked great, and I can do something like:
val byteFlow: Flow[ByteString, ByteString, _] = ??? // Some flow from somewhere else
byteFlow.frame(ByteString(0x0B), ByteString(0x1C, 0x0D)) // Implicit conversion
Problem
The implementation of FramingOps#frame
has evolved where I need to do something like this:
def frame(start: Out, end: Out): Repr[Out] = {
val maxBufferSize = math.max(start.length, end.length) - 1
val checkForMalformedChunk = stage.statefulMapConcat[Out](() => {
var buffer = Seq.empty[Any]
(chunk: Out) => {
buffer = buffer ++ chunk
if (buffer.containsSlice(start) || buffer.containsSlice(end)) ??? // Bad encoding!
buffer = buffer.takeRight(maxBufferSize)
immutable.Seq(chunk)
}
})
checkForMalformedChunk.prepend(Source.single(start)).concat(Source.single(end))
}
Having to use var buffer = Seq.empty[Any]
is ok for now but I'm sure I can do better.
This attempt breaks the implicit conversion as there is no way to provide the element type:
trait FramingOps[Elem, Out <: Seq[Elem], Mat] extends StageOps[Out, Mat] { ... }
So I figured using a TypeTag
is probably the only option:
abstract class FramingOps[Out <: Seq[_] : TypeTag, Mat] extends StageOps[Out, Mat] { ... }
Now I can get the element type at runtime by using:
implicitly[TypeTag[Out]] match { case TypeRef(_, _, List(elemType)) => elemType }
But how do I use this to create the empty sequence of the right type? Do I need to keep using reflection and provide the type parameter myslef? If so how do I do that?
Aucun commentaire:
Enregistrer un commentaire