Skip to content

Instantly share code, notes, and snippets.

@jeffmay
Last active August 29, 2015 14:13
Show Gist options
  • Save jeffmay/868116e2689fa3a359ce to your computer and use it in GitHub Desktop.
Save jeffmay/868116e2689fa3a359ce to your computer and use it in GitHub Desktop.
SecurePrinter typeclass
import scala.annotation.implicitNotFound
import scala.language.{higherKinds, implicitConversions}
/**
* A typeclass of securely printable values.
*
* Only primitive values and values that are marked as securely printable by default.
*
* You can extend new types as securely printable by adding an implicit printable to the
* companion object of the class.
*
* {{{
* class NewType
* object NewType {
* implicit lazy val printable = SecurelyPrintable.usingToString[NewType]
* }
* }}}
*/
@implicitNotFound("No implicit SecurePrinter found for type ${T}. " +
"Implement or import an implicit SecurePrinter[${T}]."
)
trait SecurePrinter[-T] {
def write(value: T): String
}
object SecurePrinter {
def of[T: SecurePrinter]: SecurePrinter[T] = implicitly
def using[T](asString: T => String): SecurePrinter[T] = new SecurePrinter[T] {
override def write(value: T): String = asString(value)
}
def usingToString[T <: AnyRef]: SecurePrinter[T] = new SecurePrinter[T] {
override def write(value: T): String = value.toString
}
implicit object SecurePrinterString extends SecurePrinter[String] {
override def write(value: String): String = value
}
implicit object SecurePrinterAnyVal extends SecurePrinter[AnyVal] {
override def write(value: AnyVal): String = value.toString
}
/**
* Creates a printer that prints the class name with all the items separated by commas.
*
* This mimics the way case classes, tuples, and Scala collections are printed.
*/
implicit def TraversableSecurePrinter[T](implicit printer: SecurePrinter[T]): SecurePrinter[Traversable[T]] = {
new SecurePrinter[Traversable[T]] {
override def write(ts: Traversable[T]): String = {
val className = ts.getClass.getSimpleName
val builder = new StringBuilder(className)
builder.append('(')
if (ts.nonEmpty) {
val iter = ts.toIterator
builder.append(printer.write(iter.next()))
while (iter.hasNext) {
builder.append(',')
builder.append(' ')
builder.append(printer.write(iter.next()))
}
}
builder.append(')')
builder.result()
}
}
}
}
@jeffmay
Copy link
Author

jeffmay commented Jan 7, 2015

Turns out I don't need C at all. I fixed it.

Thanks!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment