From 580b3f4fd73eeb42178ff3bae95cdcbf6b149e6f Mon Sep 17 00:00:00 2001 From: "dmitry.shakhtarin" Date: Wed, 20 Jun 2018 20:23:16 +0300 Subject: [PATCH] add readme and small refactoring --- README.md | 75 ++++++++++++++++++- build.sbt | 1 - .../scala/fluence/multiaddr/Multiaddr.scala | 16 ++-- .../fluence/multiaddr/MultiaddrParser.scala | 2 +- .../multiaddr/MultiaddrParseSpec.scala | 13 +--- 5 files changed, 87 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 16efae4..e4ee70a 100644 --- a/README.md +++ b/README.md @@ -1 +1,74 @@ -# scala-multiaddr \ No newline at end of file +# scala-multiaddr + +> [multiaddr](https://github.com/multiformats/multiaddr) implementation in scala + +Multiaddr is a standard way to represent addresses that: + +- Support any standard network protocols. +- Self-describe (include protocols). +- Have a binary packed format. +- Have a nice string representation. +- Encapsulate well. + +## Install + +```scala +// Bintray repo is used so far. Migration to Maven Central is planned +resolvers += Resolver.bintrayRepo("fluencelabs", "releases") + +libraryDependencies += "one.fluence" %%% "scala-multiaddr" % "0.0.1" +``` + +## Usage + +### Example + +#### Simple + +```scala +import fluence.multiaddr.Multiaddr + +val addr = "/ip4/127.0.0.1/tcp/1234" +// construct from a string (ErrorMessage return error message in ther parsing process) +val mEither: Either[ErrorMessage, Multiaddr] = Multiaddr(addr) +val m = mEither.right.get + +// true +m.address == "/ip4/127.0.0.1/tcp/1234" +``` + +#### Protocols + +```scala +// get the multiaddr protocol description objects +m.protoParameters + +//List( +// StringProtoParameter(IP4, "127.0.0.1"), +// IntProtoParameter(TCP, 1234), +// EmptyProtoParameter(HTTP) +//) +``` + +#### En/decapsulate + +```scala +m.encapsulate(Multiaddr.unsafe("/sctp/5678")) +// Multiaddr(/ip4/127.0.0.1/tcp/1234/sctp/5678,List(StringProtoParameter(IP4,127.0.0.1), IntProtoParameter(TCP,1234), IntProtoParameter(SCTP,5678))) +m.decapsulate("/tcp") // up to + inc last occurrence of subaddr +// Multiaddr(/ip4/127.0.0.1,List(StringProtoParameter(IP4,127.0.0.1))) +``` + +#### Tunneling + +Multiaddr allows expressing tunnels very nicely. + +```scala +val addr = Multiaddr.unsafe("/ip4/192.168.0.13/tcp/80") +val proxy = Multiaddr.unsafe("/ip4/10.20.30.40/tcp/443") +val addrOverProxy := proxy.encapsulate(m) +// /ip4/10.20.30.40/tcp/443/ip4/192.168.0.13/tcp/80 + +val proxyAgain = addrOverProxy.decapsulate(addr) +// /ip4/10.20.30.40/tcp/443 +``` \ No newline at end of file diff --git a/build.sbt b/build.sbt index 03250ef..ef9e307 100644 --- a/build.sbt +++ b/build.sbt @@ -39,7 +39,6 @@ lazy val `scala-multiaddr-core` = crossProject(JVMPlatform, JSPlatform) commons, libraryDependencies ++= Seq( "com.beachape" %%% "enumeratum" % "1.5.13", -// "org.typelevel" %%% "cats-core" % "1.1.0", "org.scalatest" %%% "scalatest" % "3.0.+" % Test ) ) diff --git a/core/src/main/scala/fluence/multiaddr/Multiaddr.scala b/core/src/main/scala/fluence/multiaddr/Multiaddr.scala index 57db5e4..3e259bd 100644 --- a/core/src/main/scala/fluence/multiaddr/Multiaddr.scala +++ b/core/src/main/scala/fluence/multiaddr/Multiaddr.scala @@ -20,25 +20,23 @@ package fluence.multiaddr import fluence.multiaddr.Multiaddr.ErrorMessage case class Multiaddr private(address: String, protoParameters: List[ProtoParameter]) { - override def toString: String = address - /** * Wraps a given Multiaddr, returning the resulting joined Multiaddr. * * @return new joined Multiaddr */ - def encapsulate(addr: Multiaddr): Either[ErrorMessage, Multiaddr] = { - Multiaddr(address + addr.toString) - } + def encapsulate(addr: Multiaddr): Either[ErrorMessage, Multiaddr] = Multiaddr(address + addr.address) /** * Decapsulate unwraps Multiaddr up until the given Multiaddr is found. * * @return decapsulated Multiaddr */ - def decapsulate(addr: Multiaddr): Either[ErrorMessage, Multiaddr] = { - val strAddr = addr.toString - val lastIndex = address.lastIndexOf(strAddr) + def decapsulate(addr: Multiaddr): Either[ErrorMessage, Multiaddr] = decapsulate(addr.address) + + + def decapsulate(addr: String): Either[ErrorMessage, Multiaddr] = { + val lastIndex = address.lastIndexOf(addr) if (lastIndex < 0) Right(this) else @@ -54,4 +52,6 @@ object Multiaddr { def apply(addr: String): Either[ErrorMessage, Multiaddr] = MultiaddrParser.parse(addr).map { case (trimmed, protoParameters) => new Multiaddr(trimmed, protoParameters) } + + def unsafe(addr: String): Multiaddr = apply(addr).right.get } diff --git a/core/src/main/scala/fluence/multiaddr/MultiaddrParser.scala b/core/src/main/scala/fluence/multiaddr/MultiaddrParser.scala index fc4a13e..52e930a 100644 --- a/core/src/main/scala/fluence/multiaddr/MultiaddrParser.scala +++ b/core/src/main/scala/fluence/multiaddr/MultiaddrParser.scala @@ -42,7 +42,7 @@ private[multiaddr] object MultiaddrParser { private def parseParameter(parameter: String, protocol: Protocol): Either[String, ProtoParameter] = { protocol match { - case TCP | UDP ⇒ + case TCP | UDP | SCTP ⇒ Try(parameter.toInt).toEither.right .map(n ⇒ IntProtoParameter(protocol, n)) .left diff --git a/core/src/test/scala/fluence/multiaddr/MultiaddrParseSpec.scala b/core/src/test/scala/fluence/multiaddr/MultiaddrParseSpec.scala index 7511699..05ff139 100644 --- a/core/src/test/scala/fluence/multiaddr/MultiaddrParseSpec.scala +++ b/core/src/test/scala/fluence/multiaddr/MultiaddrParseSpec.scala @@ -17,6 +17,7 @@ package fluence.multiaddr +import fluence.multiaddr.Multiaddr.ErrorMessage import org.scalatest.{Matchers, WordSpec} class MultiaddrParseSpec extends WordSpec with Matchers { @@ -66,14 +67,10 @@ class MultiaddrParseSpec extends WordSpec with Matchers { "encapsulate and decapsulate correct multiaddr" in { val addr1 = "/ip4/127.0.0.1/tcp/123" - val m1Either = Multiaddr(addr1) - m1Either.isRight shouldBe true - val m1 = m1Either.right.get + val m1 = Multiaddr.unsafe(addr1) val addr2 = "/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/udp/5000/https" - val m2Either = Multiaddr(addr2) - m2Either.isRight shouldBe true - val m2 = m2Either.right.get + val m2 = Multiaddr.unsafe(addr2) val m3Either = m1.encapsulate(m2) m3Either.isRight shouldBe true @@ -94,9 +91,7 @@ class MultiaddrParseSpec extends WordSpec with Matchers { "decapsulate correct multiaddr" in { val addr1 = "/ip4/127.0.0.1/udp/1234/sctp/5678" - val m1Either = Multiaddr(addr1) - m1Either.isRight shouldBe true - val m1 = m1Either.right.get + val m1 = Multiaddr.unsafe(addr1) val decapsulated = m1.decapsulate(Multiaddr("/sctp/5678").right.get).right.get decapsulated.address shouldBe "/ip4/127.0.0.1/udp/1234"