add readme and small refactoring

This commit is contained in:
dmitry.shakhtarin 2018-06-20 20:23:16 +03:00
parent 0480ab3710
commit 580b3f4fd7
5 changed files with 87 additions and 20 deletions

View File

@ -1 +1,74 @@
# scala-multiaddr # 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
```

View File

@ -39,7 +39,6 @@ lazy val `scala-multiaddr-core` = crossProject(JVMPlatform, JSPlatform)
commons, commons,
libraryDependencies ++= Seq( libraryDependencies ++= Seq(
"com.beachape" %%% "enumeratum" % "1.5.13", "com.beachape" %%% "enumeratum" % "1.5.13",
// "org.typelevel" %%% "cats-core" % "1.1.0",
"org.scalatest" %%% "scalatest" % "3.0.+" % Test "org.scalatest" %%% "scalatest" % "3.0.+" % Test
) )
) )

View File

@ -20,25 +20,23 @@ package fluence.multiaddr
import fluence.multiaddr.Multiaddr.ErrorMessage import fluence.multiaddr.Multiaddr.ErrorMessage
case class Multiaddr private(address: String, protoParameters: List[ProtoParameter]) { case class Multiaddr private(address: String, protoParameters: List[ProtoParameter]) {
override def toString: String = address
/** /**
* Wraps a given Multiaddr, returning the resulting joined Multiaddr. * Wraps a given Multiaddr, returning the resulting joined Multiaddr.
* *
* @return new joined Multiaddr * @return new joined Multiaddr
*/ */
def encapsulate(addr: Multiaddr): Either[ErrorMessage, Multiaddr] = { def encapsulate(addr: Multiaddr): Either[ErrorMessage, Multiaddr] = Multiaddr(address + addr.address)
Multiaddr(address + addr.toString)
}
/** /**
* Decapsulate unwraps Multiaddr up until the given Multiaddr is found. * Decapsulate unwraps Multiaddr up until the given Multiaddr is found.
* *
* @return decapsulated Multiaddr * @return decapsulated Multiaddr
*/ */
def decapsulate(addr: Multiaddr): Either[ErrorMessage, Multiaddr] = { def decapsulate(addr: Multiaddr): Either[ErrorMessage, Multiaddr] = decapsulate(addr.address)
val strAddr = addr.toString
val lastIndex = address.lastIndexOf(strAddr)
def decapsulate(addr: String): Either[ErrorMessage, Multiaddr] = {
val lastIndex = address.lastIndexOf(addr)
if (lastIndex < 0) if (lastIndex < 0)
Right(this) Right(this)
else else
@ -54,4 +52,6 @@ object Multiaddr {
def apply(addr: String): Either[ErrorMessage, Multiaddr] = MultiaddrParser.parse(addr).map { def apply(addr: String): Either[ErrorMessage, Multiaddr] = MultiaddrParser.parse(addr).map {
case (trimmed, protoParameters) => new Multiaddr(trimmed, protoParameters) case (trimmed, protoParameters) => new Multiaddr(trimmed, protoParameters)
} }
def unsafe(addr: String): Multiaddr = apply(addr).right.get
} }

View File

@ -42,7 +42,7 @@ private[multiaddr] object MultiaddrParser {
private def parseParameter(parameter: String, protocol: Protocol): Either[String, ProtoParameter] = { private def parseParameter(parameter: String, protocol: Protocol): Either[String, ProtoParameter] = {
protocol match { protocol match {
case TCP | UDP case TCP | UDP | SCTP
Try(parameter.toInt).toEither.right Try(parameter.toInt).toEither.right
.map(n IntProtoParameter(protocol, n)) .map(n IntProtoParameter(protocol, n))
.left .left

View File

@ -17,6 +17,7 @@
package fluence.multiaddr package fluence.multiaddr
import fluence.multiaddr.Multiaddr.ErrorMessage
import org.scalatest.{Matchers, WordSpec} import org.scalatest.{Matchers, WordSpec}
class MultiaddrParseSpec extends WordSpec with Matchers { class MultiaddrParseSpec extends WordSpec with Matchers {
@ -66,14 +67,10 @@ class MultiaddrParseSpec extends WordSpec with Matchers {
"encapsulate and decapsulate correct multiaddr" in { "encapsulate and decapsulate correct multiaddr" in {
val addr1 = "/ip4/127.0.0.1/tcp/123" val addr1 = "/ip4/127.0.0.1/tcp/123"
val m1Either = Multiaddr(addr1) val m1 = Multiaddr.unsafe(addr1)
m1Either.isRight shouldBe true
val m1 = m1Either.right.get
val addr2 = "/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/udp/5000/https" val addr2 = "/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/udp/5000/https"
val m2Either = Multiaddr(addr2) val m2 = Multiaddr.unsafe(addr2)
m2Either.isRight shouldBe true
val m2 = m2Either.right.get
val m3Either = m1.encapsulate(m2) val m3Either = m1.encapsulate(m2)
m3Either.isRight shouldBe true m3Either.isRight shouldBe true
@ -94,9 +91,7 @@ class MultiaddrParseSpec extends WordSpec with Matchers {
"decapsulate correct multiaddr" in { "decapsulate correct multiaddr" in {
val addr1 = "/ip4/127.0.0.1/udp/1234/sctp/5678" val addr1 = "/ip4/127.0.0.1/udp/1234/sctp/5678"
val m1Either = Multiaddr(addr1) val m1 = Multiaddr.unsafe(addr1)
m1Either.isRight shouldBe true
val m1 = m1Either.right.get
val decapsulated = m1.decapsulate(Multiaddr("/sctp/5678").right.get).right.get val decapsulated = m1.decapsulate(Multiaddr("/sctp/5678").right.get).right.get
decapsulated.address shouldBe "/ip4/127.0.0.1/udp/1234" decapsulated.address shouldBe "/ip4/127.0.0.1/udp/1234"