package scales.xml.serializers
import scales.utils._
import resources._
import scales.xml._
import java.io.Writer
import scalaz.{IterV, Enumerator, Input, EphemeralStream}
import scalaz.IterV._
trait SerializingIter {
type SerialIterT = IterV[PullType, (XmlOutput, Option[Throwable])]
import java.nio.charset.Charset
def serializeIter( output : XmlOutput, serializer : Serializer, closer : () => Unit, doc : DocLike = EmptyDoc()) : SerialIterT = {
var empties = 0
def done( status : StreamStatus ) : SerialIterT = {
closer()
Done((status.output, status.thrown), EOF[PullType])
}
def rest( status : StreamStatus, prev : PullType, serializer : Serializer )(s : Input[PullType]) : SerialIterT = {
s(el = e => {
if (status.thrown.isDefined) done(status)
else {
val r = StreamSerializer.pump((prev, e), status, serializer)
if (r.thrown.isDefined) done(r)
else Cont(rest(r, e, serializer))
}
},
empty = {
empties += 1
Cont(rest(status, prev, serializer))
},
eof = {
if (status.thrown.isDefined) done(status)
else {
val r = StreamSerializer.pump((prev, StreamSerializer.dummy), status, serializer)
val opt = serializeMisc(r.output, doc.end.misc, serializer)._2
val lastStatus = r.copy(thrown = opt)
done(lastStatus)
}})
}
def first( status : StreamStatus, serializer : Serializer )(s : Input[PullType]) : SerialIterT =
s(el = e => {
val opt = serializer.xmlDeclaration(status.output.data.encoding,
status.output.data.version).orElse{
serializeMisc(status.output, doc.prolog.misc, serializer)._2
}
val nstatus = status.copy(thrown = opt)
Cont(rest(nstatus, e, serializer))
},
empty = {
empties += 1
Cont(first(status, serializer))
},
eof = Done((status.output, Some(NoDataInStream())), EOF[PullType]))
Cont(first(StreamStatus(output), serializer))
}
def pushXmlIter( out: java.io.Writer, doc : DocLike = EmptyDoc(), version: Option[XmlVersion] = None, encoding: Option[Charset] = None )(implicit serializerFI: SerializerFactory) : (CloseOnNeed, SerialIterT) = {
val decl = doc.prolog.decl
val sd = SerializerData(out,
version.getOrElse(decl.version),
encoding.getOrElse(decl.encoding))
val xo = XmlOutput(sd)(serializerFI)
val ser = serializerFI.borrow( sd )
val closer : CloseOnNeed = new CloseOnNeed {
def doClose() {
serializerFI.giveBack(ser)
}
}
val iter = serializeIter( xo, ser, () => closer.closeResource, doc)
(closer, iter)
}
}