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

fmgp.did.framework.Transport.scala Maven / Gradle / Ivy

The newest version!
package fmgp.did.framework

import zio._
import zio.stream._
import fmgp.did._
import fmgp.did.comm.{SignedMessage, EncryptedMessage}

type TransportDIDComm[R] = Transport[R, SignedMessage | EncryptedMessage, SignedMessage | EncryptedMessage]

//TODO maybe remove the R ? Do we really need it?
/** The goal is to make this DID Comm library Transport-agnostic */
trait Transport[R, IN, OUT] { self =>

  /** Describe properties about the Flow (direction) of data for this transport */
  def transmissionFlow: Transport.TransmissionFlow

  /** Describe properties about the Type connection in this transport */
  def transmissionType: Transport.TransmissionType

  /** Send to the other side. Out going Messages */
  def outbound: ZSink[R, Transport.OutErr, OUT, Nothing, Unit]

  /** Reciving from the other side. Income Messages */
  def inbound: ZStream[R, Transport.InErr, IN]

  def id: TransportID

  def send(message: OUT): ZIO[R, Nothing, Unit] =
    ZStream.succeed(message).run(outbound)

  def provide(env: ZEnvironment[R]): Transport[Any, IN, OUT] = Transport.Provided(self, env)
}

object Transport {
  type OutErr = Nothing
  type InErr = Nothing

  private[framework] final case class Provided[Env, IN, OUT](
      transport: Transport[Env, IN, OUT],
      env: ZEnvironment[Env],
  ) extends Transport[Any, IN, OUT] {

    def transmissionFlow: Transport.TransmissionFlow = transport.transmissionFlow
    def transmissionType: Transport.TransmissionType = transport.transmissionType
    def outbound: ZSink[Any, Transport.OutErr, OUT, Nothing, Unit] = transport.outbound.provideEnvironment(env)
    def inbound: ZStream[Any, Transport.InErr, IN] = transport.inbound.provideEnvironment(env)
    def id: TransportID = transport.id
    override def send(message: OUT): ZIO[Any, Nothing, Unit] = transport.send(message).provideEnvironment(env)

    override def toString() = s"Transport.Provided(${transport}, ${env})"
  }

  // ############################
  // ### transport properties ###
  // ############################

  /** Describe properties about the Flow (direction) of data */
  enum TransmissionFlow:
    case Sending extends TransmissionFlow
    case Receiving extends TransmissionFlow
    case BothWays extends TransmissionFlow

  // object TransmissionFlow {
  //   given decoder: JsonDecoder[TransmissionFlow] = JsonDecoder.string.mapOrFail(e => safeValueOf(TransmissionFlow.valueOf(e)))
  //   given encoder: JsonEncoder[TransmissionFlow] = JsonEncoder.string.contramap((e: TransmissionFlow) => e.toString)
  // }

  /** Describe properties about the Type connection */
  enum TransmissionType:
    case SingleTransmission extends TransmissionType
    case MultiTransmissions extends TransmissionType

  // object TransmissionType {
  //   given decoder: JsonDecoder[TransmissionType] = JsonDecoder.string.mapOrFail(e => safeValueOf(TransmissionType.valueOf(e)))
  //   given encoder: JsonEncoder[TransmissionType] = JsonEncoder.string.contramap((e: TransmissionType) => e.toString)
  // }

}

object TransportID:
  val TRANSPORT_ID = "TRANSPORT_ID"
  private var transportCounter = 1 // TODO use scala.util.Random.nextLong().toString
  private def nextTransportCounter = +this.synchronized { transportCounter += 1; transportCounter }
  def apply(value: String): TransportID = value
  def apply(): TransportID = "transport:" + nextTransportCounter
  def ws: TransportID = "transport:ws:" + nextTransportCounter
  def http: TransportID = "transport:http:" + nextTransportCounter
  def http(requestID: String): TransportID = http + ":" + requestID
  def http(requestID: Option[String]): TransportID = http + requestID.map(":" + _).getOrElse("")
  extension (value: TransportID)
    def id: String = value
    def logAnnotation = LogAnnotation(TRANSPORT_ID, value)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy