All Downloads are FREE. Search and download functionalities are using the official Maven repository.

laika.io.runtime.InputRuntime.scala Maven / Gradle / Ivy

/*
 * Copyright 2012-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package laika.io.runtime

import java.io._

import cats.effect.{Sync, Resource}
import laika.io.model._
import laika.parse.SourceCursor
import laika.parse.markup.DocumentParser.DocumentInput
import cats.implicits._

import scala.io.Codec

/** Internal runtime for creating and reading from InputStreams.
  * 
  * @author Jens Halm
  */
object InputRuntime {

  def readParserInput[F[_]: Sync] (doc: TextInput[F]): F[DocumentInput] = doc.input.use {
    case PureReader(input) => 
      Sync[F].pure(DocumentInput(doc.path, SourceCursor(input, doc.path)))
    case StreamReader(reader, sizeHint) => 
      readAll(reader, sizeHint).map(source => DocumentInput(doc.path, SourceCursor(source, doc.path)))
  }

  def readAll[F[_]: Sync] (reader: Reader, sizeHint: Int): F[String] = {
    
    def read(inBuffer: Array[Char], outBuffer: StringBuilder): F[Unit] = {
      for {
        amount <- Sync[F].blocking(reader.read(inBuffer, 0, inBuffer.length))
        _      <- if (amount == -1) Sync[F].unit
                  else Sync[F].blocking(outBuffer.appendAll(inBuffer, 0, amount)) >> read(inBuffer, outBuffer)
      } yield ()
    }
    
    for {
      inBuffer  <- Sync[F].delay(new Array[Char](Math.max(sizeHint, 8)))
      outBuffer = new StringBuilder
      _         <- read(inBuffer, outBuffer)
    } yield outBuffer.toString
  }

  def binaryFileResource[F[_]: Sync] (file: File): Resource[F, InputStream] =
    Resource.fromAutoCloseable(Sync[F].delay(new BufferedInputStream(new FileInputStream(file))))

  def textFileResource[F[_]: Sync] (file: File, codec: Codec): Resource[F, Reader] =
    textStreamResource(Resource.fromAutoCloseable(Sync[F].delay(new FileInputStream(file))), codec)

  def textStreamResource[F[_]: Sync] (inputStream: F[InputStream], codec: Codec, autoClose: Boolean): Resource[F, Reader] =
    textStreamResource(if (autoClose) Resource.fromAutoCloseable(inputStream) else Resource.eval(inputStream), codec)

  def textStreamResource[F[_]: Sync](resource: Resource[F, InputStream], codec: Codec): Resource[F, Reader] =
    resource.map(in => new BufferedReader(new InputStreamReader(in, codec.charSet)))
  
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy