Skip to content

Commit

Permalink
Fix #35: Major clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
povder committed Jan 3, 2017
1 parent 765627d commit 5255919
Show file tree
Hide file tree
Showing 224 changed files with 5,415 additions and 3,709 deletions.
6 changes: 6 additions & 0 deletions .scalafmt.conf
@@ -0,0 +1,6 @@
style = default
maxColumn = 120
importSelectors = binPack
includeCurlyBraceInSelectChains = false
rewrite.rules = [SortImports]
project.git = true
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -6,7 +6,7 @@ scala:
- 2.11.8
sudo: false
install: ci/bootstrap.sh
script: sbt ++$TRAVIS_SCALA_VERSION clean coverage test coverageReport
script: sbt ++$TRAVIS_SCALA_VERSION clean scalastyle coverage test coverageReport
after_success: bash <(curl -s https://codecov.io/bash)
deploy:
skip_cleanup: true
Expand Down
37 changes: 27 additions & 10 deletions build.sbt
Expand Up @@ -28,7 +28,11 @@ lazy val commonSettings = Seq(
setNextVersion,
commitNextVersion,
pushChanges
)
),
buildInfoKeys := Vector(version, scalaVersion, git.gitHeadCommit, BuildInfoKey.action("buildTime") {
java.time.Instant.now()
}),
scalastyleFailOnError := true
)

lazy val rdbcPgsql = (project in file("."))
Expand All @@ -40,42 +44,53 @@ lazy val rdbcPgsql = (project in file("."))
.aggregate(core, scodec, nettyTransport)

lazy val core = (project in file("rdbc-pgsql-core"))
.enablePlugins(BuildInfoPlugin)
.settings(commonSettings: _*)
.settings(
name := "pgsql-core",
libraryDependencies ++= Vector(
Library.rdbcScalaApi,
Library.rdbcTypeconv,
Library.rdbcImplbase,
Library.rdbcUtil,
Library.typesafeConfig,
Library.scalaLogging,
Library.akkaStream,
Library.sourcecode
)
Library.sourcecode,
Library.scodecBits
),
buildInfoPackage := "io.rdbc.pgsql.core"
)

lazy val scodec = (project in file("rdbc-pgsql-scodec"))
lazy val scodec = (project in file("rdbc-pgsql-codec-scodec"))
.enablePlugins(BuildInfoPlugin)
.settings(commonSettings: _*)
.settings(
name := "pgsql-codec-scodec",
libraryDependencies ++= Vector(
Library.scodecBits,
Library.scodecCore
)
).dependsOn(core)
),
buildInfoPackage := "io.rdbc.pgsql.scodec"
)
.dependsOn(core)

lazy val nettyTransport = (project in file("rdbc-pgsql-transport-netty"))
.enablePlugins(BuildInfoPlugin)
.settings(commonSettings: _*)
.settings(
name := "pgsql-transport-netty",
libraryDependencies ++= Vector(
Library.nettyHandler,
Library.nettyEpoll,
Library.rdbcTypeconv,
Library.rdbcUtil,
Library.scalaLogging,
Library.logback
)
).dependsOn(core, scodec)
),
buildInfoPackage := "io.rdbc.pgsql.transport.netty"
)
.dependsOn(core, scodec)

lazy val playground = (project in file("rdbc-pgsql-playground"))
.settings(commonSettings: _*)
Expand All @@ -84,6 +99,8 @@ lazy val playground = (project in file("rdbc-pgsql-playground"))
publishArtifact := false,
bintrayReleaseOnPublish := false,
libraryDependencies ++= Vector(
"org.postgresql" % "postgresql" % "9.4.1211"
"org.postgresql" % "postgresql" % "9.4.1212",
"org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.5"
)
).dependsOn(core, scodec, nettyTransport)
)
.dependsOn(core, scodec, nettyTransport)
7 changes: 4 additions & 3 deletions project/Dependencies.scala
@@ -1,17 +1,18 @@
import sbt._

object Version {
val rdbc = "0.0.30"
val rdbc = "0.0.37"
val netty = "4.1.6.Final"
}

object Library {
val rdbcScalaApi = "io.rdbc" %% "rdbc-api-scala" % Version.rdbc
val rdbcImplbase = "io.rdbc" %% "rdbc-implbase" % Version.rdbc
val rdbcTypeconv = "io.rdbc" %% "rdbc-typeconv" % Version.rdbc
val rdbcUtil = "io.rdbc" %% "rdbc-util" % Version.rdbc
val reactiveStreams = "org.reactivestreams" % "reactive-streams" % "1.0.0"
val akkaStream = "com.typesafe.akka" %% "akka-stream" % "2.4.14"
val scodecBits = "org.scodec" %% "scodec-bits" % "1.1.2"
val akkaStream = "com.typesafe.akka" %% "akka-stream" % "2.4.16"
val scodecBits = "org.scodec" %% "scodec-bits" % "1.1.3"
val scodecCore = "org.scodec" %% "scodec-core" % "1.10.3"
val typesafeConfig = "com.typesafe" % "config" % "1.3.1"
val nettyHandler = "io.netty" % "netty-handler" % Version.netty
Expand Down
2 changes: 2 additions & 0 deletions project/plugins.sbt
Expand Up @@ -5,3 +5,5 @@ addSbtPlugin("me.lessis" % "bintray-sbt" % "0.3.0")
addSbtPlugin("de.heikoseeberger" % "sbt-header" % "1.6.0")
addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-M14")
addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.3")
addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.8.0")
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.6.1")
10 changes: 10 additions & 0 deletions rdbc-pgsql-codec-scodec/src/main/resources/reference.conf
@@ -0,0 +1,10 @@
rdbc.pgsql.codec.defaults {

msg-decoder-factory = "io.rdbc.pgsql.scodec.ScodecDecoderFactory"
msg-encoder-factory = "io.rdbc.pgsql.scodec.ScodecEncoderFactory"

pg-types-providers = [
"io.rdbc.pgsql.scodec.types.ScodecPgTypesProvider"
]

}
@@ -0,0 +1,49 @@
/*
* Copyright 2016 Krzysztof Pado
*
* 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 io.rdbc.pgsql.scodec

import _root_.scodec.bits.{BitVector, ByteVector}
import _root_.scodec.codecs._
import _root_.scodec.{Attempt, Codec, DecodeResult, SizeBound}
import io.rdbc.pgsql.core.pgstruct.ColValue

private[scodec] object ColValueCodec extends Codec[ColValue] {

private[this] val nullLength = -1

val sizeBound = SizeBound.exact(32) | SizeBound.atLeast(32)

def decode(bits: BitVector): Attempt[DecodeResult[ColValue]] = {
int32.withContext("col_val_length") //TODO maybe use "conditional" codec, check in other places if it can be used
.decode(bits)
.flatMap(lenResult => {
val len = lenResult.value
if (len == nullLength) {
Attempt.successful(DecodeResult(ColValue.Null, lenResult.remainder))
} else {
bytes(len).withContext("col_val_bytes")
.as[ColValue.NotNull]
.decode(lenResult.remainder)
}
})
}

def encode(value: ColValue): Attempt[BitVector] = value match {
case ColValue.Null => int32.unit(nullLength).encode(Unit)
case ColValue.NotNull(data) => variableSizeBytes(int32, bytes).encode(data)
}
}
@@ -0,0 +1,71 @@
/*
* Copyright 2016 Krzysztof Pado
*
* 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 io.rdbc.pgsql.scodec

import java.nio.charset.Charset

import _root_.scodec.bits.BitVector
import _root_.scodec.codecs._
import _root_.scodec.{Attempt, Codec, DecodeResult, Err, SizeBound}
import io.rdbc.pgsql.core.pgstruct.ParamValue

private[scodec] object ParamValuesCodec {

private val formatCodec = new Codec[ParamValue] {
val sizeBound = SizeBound.exact(16)

def encode(value: ParamValue): Attempt[BitVector] = {
value match {
case _: ParamValue.Textual | _: ParamValue.Null => int16.encode(0)
case _: ParamValue.Binary => int16.encode(1)
}
}

def decode(bits: BitVector): Attempt[DecodeResult[ParamValue]] = {
Attempt.failure(Err("decoding not supported"))
}
}

private def valueCodec(implicit charset: Charset) = new Codec[ParamValue] {
def sizeBound: SizeBound = SizeBound.atLeast(32)

def encode(value: ParamValue): Attempt[BitVector] = value match {
case _: ParamValue.Null => int32.encode(-1)
case ParamValue.Textual(value, _) => variableSizeBytes(int32, string).encode(value)
case ParamValue.Binary(value, _) => variableSizeBytes(int32, bytes).encode(value)
}

def decode(bits: BitVector): Attempt[Nothing] = {
Attempt.failure(Err("decoding not supported"))
}
}

def paramValues(implicit charset: Charset): Codec[Vector[ParamValue]] = new Codec[Vector[ParamValue]] {

val sizeBound: SizeBound = SizeBound.unknown

def encode(params: Vector[ParamValue]): Attempt[BitVector] = {
{
vectorOfN(int16, formatCodec) ~ vectorOfN(int16, valueCodec)
}.encode(params, params)
}

def decode(bits: BitVector): Attempt[Nothing] = {
Attempt.failure(Err("decoding not supported"))
}
}
}
Expand Up @@ -24,33 +24,15 @@ import scala.collection.mutable.ListBuffer

class PgMapCodec[K](codec: Codec[(K, String)]) extends Codec[Map[K, String]] {

private val nul = BitVector.lowByte
private[this] val nul = BitVector.lowByte

def sizeBound = SizeBound.unknown
val sizeBound = SizeBound.unknown

def encode(options: Map[K, String]) = Encoder.encodeSeq(codec)(options.toList).map(_ ++ nul)
def encode(options: Map[K, String]): Attempt[BitVector] = {
Encoder.encodeSeq(codec)(options.toList).map(_ ++ nul)
}

def decode(buffer: BitVector): Attempt[DecodeResult[Map[K, String]]] = {
val builder = ListBuffer.empty[(K, String)]
var remaining = buffer
var count = 0
var error: Option[Err] = None
while (remaining.sizeGreaterThanOrEqual(8) && remaining.slice(0, 8) != nul) {
codec.decode(remaining) match {
case Attempt.Successful(DecodeResult(value, rest)) =>
builder += value
count += 1
remaining = rest
case Attempt.Failure(err) =>
error = Some(err.pushContext(count.toString))
remaining = BitVector.empty
}
}
error match {
case None => constant(nul).withContext("collection terminator").decode(remaining).map(dr => DecodeResult(Map(builder: _*), dr.remainder))
case Some(err) => Attempt.failure(err)
}
Attempt.failure(Err("decoding not supported"))
}

override def toString = s"pgMap($codec)"
}
}
Expand Up @@ -18,17 +18,19 @@ package io.rdbc.pgsql.scodec

import _root_.scodec.bits.BitVector
import _root_.scodec.codecs._
import _root_.scodec.{Attempt, Codec, DecodeResult, SizeBound}
import io.rdbc.pgsql.core.messages.frontend._
import _root_.scodec.{Attempt, Codec, Err, SizeBound}
import io.rdbc.pgsql.core.pgstruct.ReturnColFormats

object ReturnFieldFormatsCodec extends Codec[ReturnFieldFormats] {
private[scodec] object ReturnFieldFormatsCodec extends Codec[ReturnColFormats] {
def sizeBound: SizeBound = SizeBound.atLeast(1)

def encode(value: ReturnFieldFormats): Attempt[BitVector] = value match {
case NoReturnFields | AllTextual => pgInt16.encode(0)
case AllBinary => (pgInt16 ~ pgInt16).encode(1, 1)
case SpecificFieldFormats(formats) => listOfN(pgInt16, dbValFormat).encode(formats)
def encode(value: ReturnColFormats): Attempt[BitVector] = value match {
case ReturnColFormats.None | ReturnColFormats.AllTextual => int16.encode(0)
case ReturnColFormats.AllBinary => (int16 ~ int16).encode(1, 1)
case ReturnColFormats.Specific(formats) => vectorOfN(int16, colValFormat).encode(formats)
}

def decode(bits: BitVector): Attempt[DecodeResult[ReturnFieldFormats]] = ??? //TODO
}
def decode(bits: BitVector): Attempt[Nothing] = {
Attempt.failure(Err("decoding not supported"))
}
}
Expand Up @@ -20,25 +20,30 @@ import java.nio.charset.Charset

import _root_.scodec.Attempt.{Failure, Successful}
import _root_.scodec.DecodeResult
import _root_.scodec.bits.BitVector
import _root_.scodec.bits.ByteVector
import io.rdbc.pgsql.core.codec.{Decoded, Decoder}
import io.rdbc.pgsql.core.exception.PgDecodeException
import io.rdbc.pgsql.core.messages.backend.{Header, PgBackendMessage}
import io.rdbc.pgsql.core.pgstruct.messages.backend.{MsgHeader, PgBackendMessage}
import io.rdbc.pgsql.scodec.msg.backend._

object ScodecDecoder extends Decoder {
override def decodeMsg(bytes: Array[Byte])(implicit charset: Charset): Decoded[PgBackendMessage] = {
pgBackendMessage.decode(BitVector.view(bytes)) match {
case Successful(DecodeResult(msg, remainder)) => Decoded(msg, remainder.toByteArray)
case Failure(err) => throw PgDecodeException(err.messageWithContext)
}
class ScodecDecoder(protected val charset: Charset) extends Decoder {

private[this] val codec = pgBackendMessage(charset)

def decodeMsg(bytes: ByteVector): Decoded[PgBackendMessage] = {
decode(codec, bytes)
}

def decodeHeader(bytes: ByteVector): Decoded[MsgHeader] = {
decode(header, bytes)
}

override def decodeHeader(bytes: Array[Byte]): Decoded[Header] = {
header.decode(BitVector.view(bytes)) match {
case Successful(DecodeResult(msg, remainder)) => Decoded(msg, remainder.toByteArray)
case Failure(err) => throw PgDecodeException(err.messageWithContext)
private def decode[A](decoder: scodec.Decoder[A], bytes: ByteVector): Decoded[A] = {
decoder.decode(bytes.bits) match { //TODO data copying is a major bottleneck. decide
case Successful(DecodeResult(msg, remainder)) => Decoded(msg, remainder.bytes)
case Failure(err) => throw new PgDecodeException(
s"Error occurred while decoding message ${bytes.toHex}: ${err.messageWithContext}"
)
}
//TODO code dupl
}
}
Expand Up @@ -16,8 +16,10 @@

package io.rdbc.pgsql.scodec

import java.nio.charset.Charset

import io.rdbc.pgsql.core.codec.DecoderFactory

object ScodecDecoderFactory extends DecoderFactory {
val decoder = ScodecDecoder
class ScodecDecoderFactory extends DecoderFactory {
def decoder(charset: Charset): ScodecDecoder = new ScodecDecoder(charset)
}

0 comments on commit 5255919

Please sign in to comment.