[5.2] 1a20665 VMOD blob: remove the *UC and *LC encoding schemes.

PÃ¥l Hermunn Johansen hermunn at varnish-software.com
Fri Sep 15 11:17:18 UTC 2017


commit 1a2066501ab8f704163faeea9290f9193966dcdf
Author: Geoff Simmons <geoff at uplex.de>
Date:   Mon Sep 11 22:14:33 2017 +0200

    VMOD blob: remove the *UC and *LC encoding schemes.
    
    For HEX and URL, there is now an ENUM case in {LOWER, UPPER} to
    determine the case of hex digits produced for an encoding, default
    LOWER.

diff --git a/bin/varnishtest/tests/b00051.vtc b/bin/varnishtest/tests/b00051.vtc
index ffa5bc5..c6a0125 100644
--- a/bin/varnishtest/tests/b00051.vtc
+++ b/bin/varnishtest/tests/b00051.vtc
@@ -9,10 +9,10 @@ varnish v1 -vcl+backend {
 	import blob;
 
 	sub vcl_backend_response {
-		set beresp.http.bereq_hash = blob.encode(HEXLC, bereq.hash);
+		set beresp.http.bereq_hash = blob.encode(HEX, blob=bereq.hash);
 	}
 	sub vcl_deliver {
-		set resp.http.req_hash = blob.encode(HEXLC, req.hash);
+		set resp.http.req_hash = blob.encode(HEX, blob=req.hash);
 	}
 } -start
 
diff --git a/bin/varnishtest/tests/m00033.vtc b/bin/varnishtest/tests/m00033.vtc
index cb15b5e..2340eda 100644
--- a/bin/varnishtest/tests/m00033.vtc
+++ b/bin/varnishtest/tests/m00033.vtc
@@ -10,29 +10,29 @@ varnish v1 -vcl {
 
 	sub vcl_synth {
 	    set resp.http.id =
-	      blob.encode(IDENTITY, blob.decode(IDENTITY,
+	      blob.encode(IDENTITY, blob=blob.decode(IDENTITY,
 			      "The quick brown fox jumps over the lazy dog"));
 
 	    set resp.http.hobbes =
-	      blob.encode(IDENTITY, blob.decode(IDENTITY,
+	      blob.encode(IDENTITY, blob=blob.decode(IDENTITY,
 {"Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."}));
 
 	    set resp.http.list =
-	      blob.encode(IDENTITY, blob.decode(IDENTITY,
+	      blob.encode(IDENTITY, blob=blob.decode(IDENTITY,
 			      "" + req.http.unset + req.url +
 			      "The quick brown fox jumps over " +
 			      req.http.unset + "" + req.http.unset + "" +
 			      "the lazy dog" + req.url + req.http.unset + ""));
 
 	    set resp.http.empty =
-	      blob.encode(IDENTITY, blob.decode(IDENTITY, ""));
+	      blob.encode(IDENTITY, blob=blob.decode(IDENTITY, ""));
 
 	    set resp.http.undef =
-	      blob.encode(IDENTITY, blob.decode(IDENTITY,
+	      blob.encode(IDENTITY, blob=blob.decode(IDENTITY,
 						      req.http.unset));
 
 	    set resp.http.emptylist =
-	      blob.encode(IDENTITY, blob.decode(IDENTITY,
+	      blob.encode(IDENTITY, blob=blob.decode(IDENTITY,
 			      req.http.unset + "" + req.http.unset + ""));
 
 	    set resp.http.param =
@@ -43,7 +43,7 @@ varnish v1 -vcl {
 			      encoding=IDENTITY);
 
 	    set resp.http.paramlist =
-	      blob.encode(IDENTITY, blob.decode(encoded=
+	      blob.encode(IDENTITY, blob=blob.decode(encoded=
 			      "" + req.http.unset + req.url +
 			      "The quick brown fox jumps over " +
 			      req.http.unset + "" + req.http.unset + "" +
@@ -51,7 +51,13 @@ varnish v1 -vcl {
 			      decoding=IDENTITY));
 
 	    set resp.http.truncated =
-	      blob.encode(IDENTITY, blob.decode(HEX, "666f6f00626172"));
+	      blob.encode(IDENTITY, blob=blob.decode(HEX, "666f6f00626172"));
+
+	    set resp.http.lc =
+	      blob.encode(IDENTITY, LOWER, blob.decode(IDENTITY, "Don't care"));
+
+	    set resp.http.uc =
+	      blob.encode(IDENTITY, UPPER, blob.decode(IDENTITY, "Don't care"));
 	}
 } -start
 
@@ -67,4 +73,6 @@ client c1 {
 	expect resp.http.param == "The quick brown fox jumps over the lazy dog"
 	expect resp.http.paramlist == "/The quick brown fox jumps over the lazy dog/"
 	expect resp.http.truncated == "foo"
+	expect resp.http.lc == "Don't care"
+	expect resp.http.uc == "Don't care"
 } -run
diff --git a/bin/varnishtest/tests/m00034.vtc b/bin/varnishtest/tests/m00034.vtc
index 24da94c..949df45 100644
--- a/bin/varnishtest/tests/m00034.vtc
+++ b/bin/varnishtest/tests/m00034.vtc
@@ -10,29 +10,29 @@ varnish v1 -vcl {
 
 	sub vcl_synth {
 	    set resp.http.id =
-	      blob.encode(IDENTITY, blob.decode_n(5, IDENTITY,
+	      blob.encode(IDENTITY, blob=blob.decode_n(5, IDENTITY,
 			      "The quick brown fox jumps over the lazy dog"));
 
 	    set resp.http.hobbes =
-	      blob.encode(IDENTITY, blob.decode_n(5, IDENTITY,
+	      blob.encode(IDENTITY, blob=blob.decode_n(5, IDENTITY,
 {"Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."}));
 
 	    set resp.http.list =
-	      blob.encode(IDENTITY, blob.decode_n(6, IDENTITY,
+	      blob.encode(IDENTITY, blob=blob.decode_n(6, IDENTITY,
 			      "" + req.http.unset + req.url +
 			      "The quick brown fox jumps over " +
 			      req.http.unset + "" + req.http.unset + "" +
 			      "the lazy dog" + req.url + req.http.unset + ""));
 
 	    set resp.http.empty =
-	      blob.encode(IDENTITY, blob.decode_n(5, IDENTITY, ""));
+	      blob.encode(IDENTITY, blob=blob.decode_n(5, IDENTITY, ""));
 
 	    set resp.http.undef =
-	      blob.encode(IDENTITY, blob.decode_n(5, IDENTITY,
+	      blob.encode(IDENTITY, blob=blob.decode_n(5, IDENTITY,
 						      req.http.unset));
 
 	    set resp.http.emptylist =
-	      blob.encode(IDENTITY, blob.decode_n(5, IDENTITY,
+	      blob.encode(IDENTITY, blob=blob.decode_n(5, IDENTITY,
 			      req.http.unset + "" + req.http.unset + ""));
 
 	    set resp.http.param =
@@ -43,7 +43,7 @@ varnish v1 -vcl {
 			      encoding=IDENTITY);
 
 	    set resp.http.paramlist =
-	      blob.encode(IDENTITY, blob.decode_n(encoded=
+	      blob.encode(IDENTITY, blob=blob.decode_n(encoded=
 			      "" + req.http.unset + req.url +
 			      "The quick brown fox jumps over " +
 			      req.http.unset + "" + req.http.unset + "" +
diff --git a/bin/varnishtest/tests/m00035.vtc b/bin/varnishtest/tests/m00035.vtc
index b26d151..e1aa0ff 100644
--- a/bin/varnishtest/tests/m00035.vtc
+++ b/bin/varnishtest/tests/m00035.vtc
@@ -18,39 +18,51 @@ varnish v1 -arg "-p workspace_client=256k" -vcl {
 	    set req.http.b64all =
 {"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="};
 
+	    set resp.http.hex =
+	      blob.encode(HEX, blob=blob.decode(IDENTITY, req.http.pangram));
+
 	    set resp.http.hexlc =
-	      blob.encode(HEXLC,
-			      blob.decode(IDENTITY, req.http.pangram));
+	      blob.encode(HEX, LOWER,
+	                  blob.decode(IDENTITY, req.http.pangram));
 
 	    set resp.http.hexuc =
-	      blob.encode(HEXUC,
-			      blob.decode(IDENTITY, req.http.pangram));
+	      blob.encode(HEX, UPPER,
+			  blob.decode(IDENTITY, req.http.pangram));
+
+	    set resp.http.hobbes =
+	      blob.encode(HEX, blob=blob.decode(IDENTITY, req.http.hobbes));
 
 	    set resp.http.hobbeslc =
-	      blob.encode(HEXLC, blob.decode(IDENTITY, req.http.hobbes));
+	      blob.encode(HEX, LOWER, blob.decode(IDENTITY, req.http.hobbes));
 
 	    set resp.http.hobbesuc =
-	      blob.encode(HEXUC, blob.decode(IDENTITY, req.http.hobbes));
+	      blob.encode(HEX, UPPER, blob.decode(IDENTITY, req.http.hobbes));
+
+	    set resp.http.all =
+	      blob.encode(HEX, blob=blob.decode(BASE64, req.http.b64all));
 
 	    set resp.http.all-lc =
-	      blob.encode(HEXLC, blob.decode(BASE64, req.http.b64all));
+	      blob.encode(HEX, LOWER, blob.decode(BASE64, req.http.b64all));
 
 	    set resp.http.all-uc =
-	      blob.encode(HEXUC, blob.decode(BASE64, req.http.b64all));
+	      blob.encode(HEX, UPPER, blob.decode(BASE64, req.http.b64all));
+
+	    set resp.http.empty =
+	      blob.encode(HEX, blob=blob.decode(IDENTITY, ""));
 
 	    set resp.http.empty-lc =
-	      blob.encode(HEXLC, blob.decode(IDENTITY, ""));
+	      blob.encode(HEX, LOWER, blob.decode(IDENTITY, ""));
 
 	    set resp.http.empty-uc =
-	      blob.encode(HEXUC, blob.decode(IDENTITY, ""));
+	      blob.encode(HEX, UPPER, blob.decode(IDENTITY, ""));
 
 	    set resp.http.hexlcparam =
 	      blob.encode(blob=blob.decode(IDENTITY, req.http.pangram),
-			     encoding=HEXLC);
+			  case=LOWER, encoding=HEX);
 
 	    set resp.http.hexucparam =
 	      blob.encode(blob=blob.decode(IDENTITY, req.http.pangram),
-			     encoding=HEXUC);
+			  case=UPPER, encoding=HEX);
 
 	    set req.http.hexucfoobar = "666F6F206261722062617A2071757578";
 	    set req.http.hexlcfoobar = std.tolower(req.http.hexucfoobar);
@@ -64,51 +76,51 @@ varnish v1 -arg "-p workspace_client=256k" -vcl {
 
 	    set resp.http.decuc =
 	      blob.encode(IDENTITY,
-			     blob.decode(HEX, req.http.hexucfoobar));
+			  blob=blob.decode(HEX, req.http.hexucfoobar));
 
 	    set resp.http.declc =
 	      blob.encode(IDENTITY,
-			     blob.decode(HEX, req.http.hexlcfoobar));
+			  blob=blob.decode(HEX, req.http.hexlcfoobar));
 
 	    set resp.http.dechobbesuc =
 	      blob.encode(IDENTITY,
-			     blob.decode(HEX, req.http.hexhobbesuc));
+			  blob=blob.decode(HEX, req.http.hexhobbesuc));
 
 	    set resp.http.dechobbeslc =
 	      blob.encode(IDENTITY,
-			     blob.decode(HEX, req.http.hexhobbeslc));
+			  blob=blob.decode(HEX, req.http.hexhobbeslc));
 
 	    set resp.http.decalluc =
-	      blob.encode(BASE64, blob.decode(HEX, req.http.hexalluc));
+	      blob.encode(BASE64, blob=blob.decode(HEX, req.http.hexalluc));
 
 	    set resp.http.decalllc =
-	      blob.encode(BASE64, blob.decode(HEX, req.http.hexalllc));
+	      blob.encode(BASE64, blob=blob.decode(HEX, req.http.hexalllc));
 
 	    set resp.http.decallucodd =
-	      blob.encode(BASE64, blob.decode(HEX,
-						      req.http.hexallucodd));
+	      blob.encode(BASE64, blob=blob.decode(HEX,
+						   req.http.hexallucodd));
 
 	    set resp.http.decalllcodd =
-	      blob.encode(BASE64, blob.decode(HEX,
-						      req.http.hexalllcodd));
+	      blob.encode(BASE64, blob=blob.decode(HEX,
+						   req.http.hexalllcodd));
 
 	    set resp.http.decempty =
-	      blob.encode(IDENTITY, blob.decode(HEX, ""));
+	      blob.encode(IDENTITY, blob=blob.decode(HEX, ""));
 
 	    set resp.http.decemptybyte =
-	      blob.encode(IDENTITY, blob.decode(HEX, "00"));
+	      blob.encode(IDENTITY, blob=blob.decode(HEX, "00"));
 
 	    set resp.http.decemptynibble =
-	      blob.encode(IDENTITY, blob.decode(HEX, "0"));
+	      blob.encode(IDENTITY, blob=blob.decode(HEX, "0"));
 
 	    set resp.http.decemptypieces =
 	      blob.encode(IDENTITY,
-			     blob.decode(HEX, req.http.unset + ""
-					    + req.http.unset + ""));
+			  blob=blob.decode(HEX, req.http.unset + ""
+					        + req.http.unset + ""));
 
 	    set req.http.part1 = "666";
 	    set resp.http.dec2pieces =
-	      blob.encode(IDENTITY, blob.decode(HEX, req.http.part1 +
+	      blob.encode(IDENTITY, blob=blob.decode(HEX, req.http.part1 +
 			     "F6F206261722062617A2071757578"));
 
 	    set req.http.part2 = "57578";
@@ -119,11 +131,11 @@ varnish v1 -arg "-p workspace_client=256k" -vcl {
 			     encoding=IDENTITY);
 
 	    set resp.http.dec3pieces =
-	      blob.encode(IDENTITY, blob.decode(HEX, req.http.part1 +
+	      blob.encode(IDENTITY, blob=blob.decode(HEX, req.http.part1 +
 			     "F6F206261722062617A20717" + req.http.part2));
 
 	    set resp.http.decmanypieces =
-	      blob.encode(IDENTITY, blob.decode(HEX, "" + req.http.unset
+	      blob.encode(IDENTITY, blob=blob.decode(HEX, "" + req.http.unset
 			     + req.http.part1 + req.http.unset + ""
 			     + req.http.unset + "" + "F6F206261722062617A20717"
 			     + "" + req.http.unset + req.http.part2
@@ -134,14 +146,18 @@ varnish v1 -arg "-p workspace_client=256k" -vcl {
 client c1 {
 	txreq -url "/"
 	rxresp
-	expect resp.http.hexlc == "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67"
+	expect resp.http.hex == "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67"
+	expect resp.http.hexlc == resp.http.hex
 	expect resp.http.hexuc == "54686520717569636B2062726F776E20666F78206A756D7073206F76657220746865206C617A7920646F67"
-	expect resp.http.hobbeslc == "4d616e2069732064697374696e677569736865642c206e6f74206f6e6c792062792068697320726561736f6e2c2062757420627920746869732073696e67756c61722070617373696f6e2066726f6d206f7468657220616e696d616c732c2077686963682069732061206c757374206f6620746865206d696e642c20746861742062792061207065727365766572616e6365206f662064656c6967687420696e2074686520636f6e74696e75656420616e6420696e6465666174696761626c652067656e65726174696f6e206f66206b6e6f776c656467652c2065786365656473207468652073686f727420766568656d656e6365206f6620616e79206361726e616c20706c6561737572652e"
+	expect resp.http.hobbes == "4d616e2069732064697374696e677569736865642c206e6f74206f6e6c792062792068697320726561736f6e2c2062757420627920746869732073696e67756c61722070617373696f6e2066726f6d206f7468657220616e696d616c732c2077686963682069732061206c757374206f6620746865206d696e642c20746861742062792061207065727365766572616e6365206f662064656c6967687420696e2074686520636f6e74696e75656420616e6420696e6465666174696761626c652067656e65726174696f6e206f66206b6e6f776c656467652c2065786365656473207468652073686f727420766568656d656e6365206f6620616e79206361726e616c20706c6561737572652e"
+	expect resp.http.hobbeslc == resp.http.hobbes
 	expect resp.http.hobbesuc == "4D616E2069732064697374696E677569736865642C206E6F74206F6E6C792062792068697320726561736F6E2C2062757420627920746869732073696E67756C61722070617373696F6E2066726F6D206F7468657220616E696D616C732C2077686963682069732061206C757374206F6620746865206D696E642C20746861742062792061207065727365766572616E6365206F662064656C6967687420696E2074686520636F6E74696E75656420616E6420696E6465666174696761626C652067656E65726174696F6E206F66206B6E6F776C656467652C2065786365656473207468652073686F727420766568656D656E6365206F6620616E79206361726E616C20706C6561737572652E"
+	expect resp.http.all == "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
 	expect resp.http.all-uc == "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"
-	expect resp.http.all-lc == "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
+	expect resp.http.all-lc == resp.http.all
+	expect resp.http.empty == ""
 	expect resp.http.empty-uc == ""
-	expect resp.http.empty-lc == ""
+	expect resp.http.empty-lc == resp.http.empty
 	expect resp.http.hexlcparam == "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67"
 	expect resp.http.hexucparam == "54686520717569636B2062726F776E20666F78206A756D7073206F76657220746865206C617A7920646F67"
 	expect resp.http.decuc == "foo bar baz quux"
@@ -174,7 +190,7 @@ varnish v1 -vcl+backend {
 
 	sub vcl_deliver {
 	  set req.http.foo = "123";
-	  set resp.http.badhex = blob.encode(HEXUC,
+	  set resp.http.badhex = blob.encode(HEX, UPPER,
 				 blob.decode(HEX, "g" + req.http.foo));
 	}
 }
diff --git a/bin/varnishtest/tests/m00036.vtc b/bin/varnishtest/tests/m00036.vtc
index 21ff627..cf6335b 100644
--- a/bin/varnishtest/tests/m00036.vtc
+++ b/bin/varnishtest/tests/m00036.vtc
@@ -18,38 +18,41 @@ varnish v1 -vcl {
 {"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="};
 
 	    set resp.http.hexlc =
-	      blob.encode(HEXLC,
-			      blob.decode_n(5, IDENTITY, req.http.pangram));
+	      blob.encode(HEX,
+			  blob=blob.decode_n(5, IDENTITY, req.http.pangram));
 
 	    set resp.http.hexuc =
-	      blob.encode(HEXUC,
-			      blob.decode_n(5, IDENTITY, req.http.pangram));
+	      blob.encode(HEX, UPPER,
+			  blob.decode_n(5, IDENTITY, req.http.pangram));
 
 	    set resp.http.hobbeslc =
-	      blob.encode(HEXLC, blob.decode_n(5, IDENTITY, req.http.hobbes));
+	      blob.encode(HEX,
+	                  blob=blob.decode_n(5, IDENTITY, req.http.hobbes));
 
 	    set resp.http.hobbesuc =
-	      blob.encode(HEXUC, blob.decode_n(5, IDENTITY, req.http.hobbes));
+	      blob.encode(HEX, UPPER,
+	                  blob.decode_n(5, IDENTITY, req.http.hobbes));
 
 	    set resp.http.all-lc =
-	      blob.encode(HEXLC, blob.decode_n(8, BASE64, req.http.b64all));
+	      blob.encode(HEX, blob=blob.decode_n(8, BASE64, req.http.b64all));
 
 	    set resp.http.all-uc =
-	      blob.encode(HEXUC, blob.decode_n(8, BASE64, req.http.b64all));
+	      blob.encode(HEX, UPPER,
+	                  blob.decode_n(8, BASE64, req.http.b64all));
 
 	    set resp.http.empty-lc =
-	      blob.encode(HEXLC, blob.decode_n(5, IDENTITY, ""));
+	      blob.encode(HEX, blob=blob.decode_n(5, IDENTITY, ""));
 
 	    set resp.http.empty-uc =
-	      blob.encode(HEXUC, blob.decode_n(5, IDENTITY, ""));
+	      blob.encode(HEX, UPPER, blob.decode_n(5, IDENTITY, ""));
 
 	    set resp.http.hexlcparam =
 	      blob.encode(blob=blob.decode_n(5, IDENTITY, req.http.pangram),
-			     encoding=HEXLC);
+			     encoding=HEX, case=LOWER);
 
 	    set resp.http.hexucparam =
 	      blob.encode(blob=blob.decode_n(5, IDENTITY, req.http.pangram),
-			     encoding=HEXUC);
+			     encoding=HEX, case=UPPER);
 
 	    set req.http.hexucfoobar = "666F6F206261722062617A2071757578";
 	    set req.http.hexlcfoobar = std.tolower(req.http.hexucfoobar);
@@ -63,51 +66,53 @@ varnish v1 -vcl {
 
 	    set resp.http.decuc =
 	      blob.encode(IDENTITY,
-			     blob.decode_n(10, HEX, req.http.hexucfoobar));
+			  blob=blob.decode_n(10, HEX, req.http.hexucfoobar));
 
 	    set resp.http.declc =
 	      blob.encode(IDENTITY,
-			     blob.decode_n(10, HEX, req.http.hexlcfoobar));
+			  blob=blob.decode_n(10, HEX, req.http.hexlcfoobar));
 
 	    set resp.http.dechobbesuc =
 	      blob.encode(IDENTITY,
-			     blob.decode_n(12, HEX, req.http.hexhobbesuc));
+			  blob=blob.decode_n(12, HEX, req.http.hexhobbesuc));
 
 	    set resp.http.dechobbeslc =
 	      blob.encode(IDENTITY,
-			     blob.decode_n(12, HEX, req.http.hexhobbeslc));
+			  blob=blob.decode_n(12, HEX, req.http.hexhobbeslc));
 
 	    set resp.http.decalluc =
-	      blob.encode(BASE64, blob.decode_n(12, HEX, req.http.hexalluc));
+	      blob.encode(BASE64,
+	                  blob=blob.decode_n(12, HEX, req.http.hexalluc));
 
 	    set resp.http.decalllc =
-	      blob.encode(BASE64, blob.decode_n(12, HEX, req.http.hexalllc));
+	      blob.encode(BASE64,
+	                  blob=blob.decode_n(12, HEX, req.http.hexalllc));
 
 	    set resp.http.decallucodd =
-	      blob.encode(BASE64, blob.decode_n(11, HEX,
-						      req.http.hexallucodd));
+	      blob.encode(BASE64, blob=blob.decode_n(11, HEX,
+						     req.http.hexallucodd));
 
 	    set resp.http.decalllcodd =
-	      blob.encode(BASE64, blob.decode_n(11, HEX,
-						      req.http.hexalllcodd));
+	      blob.encode(BASE64, blob=blob.decode_n(11, HEX,
+						     req.http.hexalllcodd));
 
 	    set resp.http.decempty =
-	      blob.encode(IDENTITY, blob.decode_n(5, HEX, ""));
+	      blob.encode(IDENTITY, blob=blob.decode_n(5, HEX, ""));
 
 	    set resp.http.decemptybyte =
-	      blob.encode(IDENTITY, blob.decode_n(1, HEX, "00"));
+	      blob.encode(IDENTITY, blob=blob.decode_n(1, HEX, "00"));
 
 	    set resp.http.decemptynibble =
-	      blob.encode(IDENTITY, blob.decode_n(2, HEX, "0"));
+	      blob.encode(IDENTITY, blob=blob.decode_n(2, HEX, "0"));
 
 	    set resp.http.decemptypieces =
 	      blob.encode(IDENTITY,
-			     blob.decode_n(5, HEX, req.http.unset + ""
-					    + req.http.unset + ""));
+			  blob=blob.decode_n(5, HEX, req.http.unset + ""
+					     + req.http.unset + ""));
 
 	    set req.http.part1 = "666";
 	    set resp.http.dec2pieces =
-	      blob.encode(IDENTITY, blob.decode_n(6, HEX, req.http.part1 +
+	      blob.encode(IDENTITY, blob=blob.decode_n(6, HEX, req.http.part1 +
 			     "F6F206261722062617A2071757578"));
 
 	    set req.http.part2 = "57578";
@@ -118,11 +123,12 @@ varnish v1 -vcl {
 			     encoding=IDENTITY);
 
 	    set resp.http.dec3pieces =
-	      blob.encode(IDENTITY, blob.decode_n(30, HEX, req.http.part1 +
+	      blob.encode(IDENTITY, blob=blob.decode_n(30, HEX, req.http.part1 +
 			     "F6F206261722062617A20717" + req.http.part2));
 
 	    set resp.http.decmanypieces =
-	      blob.encode(IDENTITY, blob.decode_n(20, HEX, "" + req.http.unset
+	      blob.encode(IDENTITY, blob=blob.decode_n(20, HEX, ""
+	                     + req.http.unset
 			     + req.http.part1 + req.http.unset + ""
 			     + req.http.unset + "" + "F6F206261722062617A20717"
 			     + "" + req.http.unset + req.http.part2
@@ -173,7 +179,7 @@ varnish v1 -vcl+backend {
 
 	sub vcl_deliver {
 	  set req.http.foo = "123";
-	  set resp.http.badhex = blob.encode(HEXUC,
+	  set resp.http.badhex = blob.encode(HEX, UPPER,
 				 blob.decode_n(2, HEX, "g" + req.http.foo));
 	}
 }
diff --git a/bin/varnishtest/tests/m00037.vtc b/bin/varnishtest/tests/m00037.vtc
index 13dc2d5..25a7dee 100644
--- a/bin/varnishtest/tests/m00037.vtc
+++ b/bin/varnishtest/tests/m00037.vtc
@@ -18,69 +18,93 @@ varnish v1 -vcl {
 {"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a09f9e9d9c9b9a999897969594939291908f8e8d8c8b8a898887868584838281807f7e7d7c7b7a797877767574737271706f6e6d6c6b6a696867666564636261605f5e5d5c5b5a595857565554535251504f4e4d4c4b4a494847464544434241403f3e3d3c3b3a393837363534333231302f2e2d2c2b2a292827262524232221201f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100"};
 
 	    set resp.http.b64 =
-	      blob.encode(BASE64, blob.decode(IDENTITY,
+	      blob.encode(BASE64, blob=blob.decode(IDENTITY,
+						      req.http.pangram));
+
+	    set resp.http.b64lc =
+	      blob.encode(BASE64, LOWER, blob.decode(IDENTITY,
+						      req.http.pangram));
+
+	    set resp.http.b64uc =
+	      blob.encode(BASE64, UPPER, blob.decode(IDENTITY,
 						      req.http.pangram));
 
 	    set resp.http.b64hobbes =
-	      blob.encode(BASE64, blob.decode(IDENTITY,
+	      blob.encode(BASE64, blob=blob.decode(IDENTITY,
 						      req.http.hobbes));
 
 	    set resp.http.b64all =
-	      blob.encode(BASE64, blob.decode(HEX, req.http.hexall));
+	      blob.encode(BASE64, blob=blob.decode(HEX, req.http.hexall));
 
 	    set resp.http.b64url =
 	      blob.encode(BASE64URL,
-			      blob.decode(IDENTITY, req.http.pangram));
+			  blob=blob.decode(IDENTITY, req.http.pangram));
+
+	    set resp.http.b64urllc =
+	      blob.encode(BASE64URL, LOWER,
+			  blob.decode(IDENTITY, req.http.pangram));
+
+	    set resp.http.b64urluc =
+	      blob.encode(BASE64URL, UPPER,
+			  blob.decode(IDENTITY, req.http.pangram));
 
 	    set resp.http.b64urlhobbes =
 	      blob.encode(BASE64URL,
-			      blob.decode(IDENTITY, req.http.hobbes));
+			  blob=blob.decode(IDENTITY, req.http.hobbes));
 
 	    set resp.http.b64urlall =
-	      blob.encode(BASE64URL, blob.decode(HEX, req.http.hexall));
+	      blob.encode(BASE64URL, blob=blob.decode(HEX, req.http.hexall));
 
 	    set resp.http.b64urlnopad =
 	      blob.encode(BASE64URLNOPAD,
-			      blob.decode(IDENTITY, req.http.pangram));
+			  blob=blob.decode(IDENTITY, req.http.pangram));
+
+	    set resp.http.b64urlnopadlc =
+	      blob.encode(BASE64URLNOPAD, LOWER,
+			  blob.decode(IDENTITY, req.http.pangram));
+
+	    set resp.http.b64urlnopaduc =
+	      blob.encode(BASE64URLNOPAD, UPPER,
+			  blob.decode(IDENTITY, req.http.pangram));
 
 	    set resp.http.b64nopadhobbes =
 	      blob.encode(BASE64URLNOPAD,
-			      blob.decode(IDENTITY, req.http.hobbes));
+			  blob=blob.decode(IDENTITY, req.http.hobbes));
 
 	    set resp.http.b64nopadall =
 	      blob.encode(BASE64URLNOPAD,
-			      blob.decode(HEX, req.http.hexall));
+			  blob=blob.decode(HEX, req.http.hexall));
 
 	    set resp.http.b64empty =
-	      blob.encode(BASE64, blob.decode(IDENTITY, ""));
+	      blob.encode(BASE64, blob=blob.decode(IDENTITY, ""));
 	    set resp.http.urlempty =
-	      blob.encode(BASE64URL, blob.decode(IDENTITY, ""));
+	      blob.encode(BASE64URL, blob=blob.decode(IDENTITY, ""));
 	    set resp.http.nopadempty =
-	      blob.encode(BASE64URLNOPAD, blob.decode(IDENTITY, ""));
+	      blob.encode(BASE64URLNOPAD, blob=blob.decode(IDENTITY, ""));
 
 	    set resp.http.b64param =
 	      blob.encode(blob=blob.decode(IDENTITY, req.http.pangram),
-			      encoding=BASE64);
+			  encoding=BASE64, case=LOWER);
 
 	    set resp.http.b64urlparam =
 	      blob.encode(blob=blob.decode(IDENTITY, req.http.pangram),
-			      encoding=BASE64URL);
+			  encoding=BASE64URL, case=UPPER);
 
 	    set resp.http.b64urlnopadparam =
 	      blob.encode(blob=blob.decode(IDENTITY, req.http.pangram),
-			      encoding=BASE64URLNOPAD);
+			  encoding=BASE64URLNOPAD, case=LOWER);
 
 	    set resp.http.b64xcode =
-		blob.transcode(IDENTITY, BASE64, req.url + "Hello world" +
-				   req.url);
+		blob.transcode(IDENTITY, BASE64,
+		               encoded=req.url + "Hello world" + req.url);
 
 	    set resp.http.b64urlxcode =
-		blob.transcode(IDENTITY, BASE64URL, req.url + "Hello world" +
-				   req.url);
+		blob.transcode(IDENTITY, BASE64URL,
+		               encoded=req.url + "Hello world" + req.url);
 
 	    set resp.http.b64urlnopadxcode =
 	      blob.transcode(IDENTITY, BASE64URLNOPAD,
-				 req.url + "Hello world" + req.url);
+			     encoded=req.url + "Hello world" + req.url);
 	}
 } -start
 
@@ -88,12 +112,18 @@ client c1 {
 	txreq -url "/"
 	rxresp
 	expect resp.http.b64 == "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="
+	expect resp.http.b64lc == resp.http.b64
+	expect resp.http.b64uc == resp.http.b64
 	expect resp.http.b64hobbes == "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="
 	expect resp.http.b64all == "//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAA=="
 	expect resp.http.b64url == "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="
+	expect resp.http.b64urllc == resp.http.b64url
+	expect resp.http.b64urluc == resp.http.b64url
 	expect resp.http.b64urlhobbes == "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="
 	expect resp.http.b64urlall == "__79_Pv6-fj39vX08_Lx8O_u7ezr6uno5-bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL--vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI-OjYyLiomIh4aFhIOCgYB_fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAA=="
 	expect resp.http.b64urlnopad == "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw"
+	expect resp.http.b64urlnopadlc == resp.http.b64urlnopad
+	expect resp.http.b64urlnopaduc == resp.http.b64urlnopad
 	expect resp.http.b64nopadhobbes == "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4"
 	expect resp.http.b64nopadall == "__79_Pv6-fj39vX08_Lx8O_u7ezr6uno5-bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL--vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI-OjYyLiomIh4aFhIOCgYB_fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAA"
 	expect resp.http.b64empty == ""
@@ -126,66 +156,66 @@ varnish v1 -vcl {
 	    set req.http.allurl =
 {"AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZaaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzz0000111122223333444455556666777788889999----____"};
 
-	    set resp.http.dec = blob.encode(IDENTITY,
+	    set resp.http.dec = blob.encode(IDENTITY, blob=
 				blob.decode(BASE64, req.http.foobarbazquux));
 
 	    set resp.http.dec2
 	      = blob.encode(IDENTITY,
-				blob.decode(BASE64, req.http.pangram));
+			    blob=blob.decode(BASE64, req.http.pangram));
 
 	    set resp.http.b64dechobbes =
 	      blob.encode(IDENTITY,
-			      blob.decode(BASE64, req.http.hobbes));
+			  blob=blob.decode(BASE64, req.http.hobbes));
 
 	    set resp.http.b64decall =
-	      blob.encode(HEXLC, blob.decode(BASE64, req.http.all));
+	      blob.encode(HEX, blob=blob.decode(BASE64, req.http.all));
 
 	    set resp.http.urldechobbes =
-	      blob.encode(IDENTITY, blob.decode(BASE64URL,
+	      blob.encode(IDENTITY, blob=blob.decode(BASE64URL,
 						      req.http.hobbes));
 
 	    set resp.http.urldecall =
-	      blob.encode(HEXLC,
-			      blob.decode(BASE64URL, req.http.allurl));
+	      blob.encode(HEX,
+			  blob=blob.decode(BASE64URL, req.http.allurl));
 
 	    set resp.http.nopaddechobbes =
-	      blob.encode(IDENTITY, blob.decode(BASE64URLNOPAD,
+	      blob.encode(IDENTITY, blob=blob.decode(BASE64URLNOPAD,
 						      req.http.hobbesnopad));
 
 	    set resp.http.nopaddecall =
-	      blob.encode(HEXLC,
-			      blob.decode(BASE64URLNOPAD, req.http.allurl));
+	      blob.encode(HEX,
+			  blob=blob.decode(BASE64URLNOPAD, req.http.allurl));
 
 	    set resp.http.b64empty =
-	      blob.encode(IDENTITY, blob.decode(BASE64, ""));
+	      blob.encode(IDENTITY, blob=blob.decode(BASE64, ""));
 	    set resp.http.urlempty =
-	      blob.encode(IDENTITY, blob.decode(BASE64URL, ""));
+	      blob.encode(IDENTITY, blob=blob.decode(BASE64URL, ""));
 	    set resp.http.nopadempty =
-	      blob.encode(IDENTITY, blob.decode(BASE64URLNOPAD, ""));
+	      blob.encode(IDENTITY, blob=blob.decode(BASE64URLNOPAD, ""));
 	    set resp.http.emptypieces =
-	      blob.encode(IDENTITY,
+	      blob.encode(IDENTITY, blob=
 	      blob.decode(BASE64, req.http.unset + "" + req.http.unset
 				      + "" + req.http.unset + ""));
 
 	    set resp.http.decenc
 	      = blob.encode(BASE64,
-				blob.decode(BASE64, req.http.foobarbazquux));
+			    blob=blob.decode(BASE64, req.http.foobarbazquux));
 
 	    set resp.http.l = "L";
 	    set resp.http.dec2pieces
-	      = blob.encode(IDENTITY, blob.decode(BASE64,
+	      = blob.encode(IDENTITY, blob=blob.decode(BASE64,
 				resp.http.l + "0hlbGxvIHdvcmxkLw=="));
 
 	    set resp.http.pad = "==";
 	    set resp.http.dec3pieces
-	      = blob.encode(IDENTITY, blob.decode(BASE64,
+	      = blob.encode(IDENTITY, blob=blob.decode(BASE64,
 				resp.http.l + "0hlbGxvIHdvcmxkLw"
 				+ resp.http.pad));
 
 	    set resp.http.mid1 = "GxvI";
 	    set resp.http.mid2 = "dvcmx";
 	    set resp.http.dec7pieces
-	      = blob.encode(IDENTITY, blob.decode(BASE64,
+	      = blob.encode(IDENTITY, blob=blob.decode(BASE64,
 				resp.http.l + "0hlb" + resp.http.mid1
 				+ "H" + resp.http.mid2 + "kLw"
 				+ resp.http.pad));
@@ -197,21 +227,21 @@ varnish v1 -vcl {
 				encoding=IDENTITY);
 
 	    set resp.http.decnopad = blob.encode(IDENTITY,
-				     blob.decode(BASE64URLNOPAD,
+				     blob=blob.decode(BASE64URLNOPAD,
 						     "L0hlbGxvIHdvcmxkLw"));
 
 	    set resp.http.decnopad2pieces
-	      = blob.encode(IDENTITY, blob.decode(BASE64URLNOPAD,
+	      = blob.encode(IDENTITY, blob=blob.decode(BASE64URLNOPAD,
 				resp.http.l + "0hlbGxvIHdvcmxkLw"));
 
 	    set resp.http.decnopad6pieces
-	      = blob.encode(IDENTITY, blob.decode(BASE64URLNOPAD,
+	      = blob.encode(IDENTITY, blob=blob.decode(BASE64URLNOPAD,
 				resp.http.l + "0hlb" + resp.http.mid1
 				+ "H" + resp.http.mid2 + "kLw"));
 
 	    set resp.http.decnopadlong
 	      = blob.encode(IDENTITY,
-		blob.decode(BASE64URLNOPAD,
+		blob=blob.decode(BASE64URLNOPAD,
 		"VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw"
 			       ));
 
@@ -258,15 +288,15 @@ varnish v1 -vcl+backend {
 	  set req.http.foo = "AAA=";
 	  if (req.url == "/base64") {
 		set resp.http.bad64 = blob.encode(IDENTITY,
-		    blob.decode(BASE64, "-_-_" + req.http.foo));
+		    blob=blob.decode(BASE64, "-_-_" + req.http.foo));
 	  }
 	  elsif (req.url == "/base64url") {
 		set resp.http.badurl = blob.encode(IDENTITY,
-		    blob.decode(BASE64URL, "+/+/" + req.http.foo));
+		    blob=blob.decode(BASE64URL, "+/+/" + req.http.foo));
 	  }
 	  elsif (req.url == "/base64urlnopad") {
 		set resp.http.badpad = blob.encode(IDENTITY,
-		    blob.decode(BASE64URLNOPAD, "TWFu" + req.http.foo));
+		    blob=blob.decode(BASE64URLNOPAD, "TWFu" + req.http.foo));
 	  }
 	}
 }
diff --git a/bin/varnishtest/tests/m00038.vtc b/bin/varnishtest/tests/m00038.vtc
index 894618d..4e7e334 100644
--- a/bin/varnishtest/tests/m00038.vtc
+++ b/bin/varnishtest/tests/m00038.vtc
@@ -22,82 +22,80 @@ varnish v1 -vcl {
 
 	    set resp.http.dec
 	      = blob.encode(IDENTITY,
-				blob.decode_n(8, BASE64,
+			    blob=blob.decode_n(8, BASE64,
 						  req.http.foobarbazquux));
 
 	    set resp.http.deceq
 	      = blob.encode(IDENTITY,
-				blob.decode_n(20, BASE64,
+			    blob=blob.decode_n(20, BASE64,
 						  req.http.foobarbazquux));
 
 	    set resp.http.declong
 	      = blob.encode(IDENTITY,
-				blob.decode_n(30, BASE64,
+			    blob=blob.decode_n(30, BASE64,
 						  req.http.foobarbazquux));
 
 	    set resp.http.dec2
 	      = blob.encode(IDENTITY,
-				blob.decode_n(12, BASE64, req.http.pangram));
+			    blob=blob.decode_n(12, BASE64, req.http.pangram));
 
 	    set resp.http.b64dechobbes =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(24, BASE64, req.http.hobbes));
+			  blob=blob.decode_n(24, BASE64, req.http.hobbes));
 
 	    set resp.http.b64decall =
-	       blob.encode(HEXLC, blob.decode_n(128, BASE64,
-							req.http.all));
+	       blob.encode(HEX, blob=blob.decode_n(128, BASE64, req.http.all));
 
 	    set resp.http.urldechobbes =
-	      blob.encode(IDENTITY, blob.decode_n(180, BASE64URL,
+	      blob.encode(IDENTITY, blob=blob.decode_n(180, BASE64URL,
 							  req.http.hobbes));
 
 	    set resp.http.urldecall =
-	      blob.encode(HEXLC,
-			      blob.decode_n(256, BASE64URL,
+	      blob.encode(HEX,
+			      blob=blob.decode_n(256, BASE64URL,
 						req.http.allurl));
 
 	    set resp.http.nopaddechobbes =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(500, BASE64URLNOPAD,
+			      blob=blob.decode_n(500, BASE64URLNOPAD,
 						req.http.hobbesnopad));
 
 	    set resp.http.nopaddecall =
-	      blob.encode(HEXLC,
-			      blob.decode_n(256, BASE64URLNOPAD,
-						req.http.allurl));
+	      blob.encode(HEX, blob=blob.decode_n(256, BASE64URLNOPAD,
+						  req.http.allurl));
 
 	    set resp.http.b64empty =
-	      blob.encode(IDENTITY, blob.decode_n(0, BASE64, ""));
+	      blob.encode(IDENTITY, blob=blob.decode_n(0, BASE64, ""));
 	    set resp.http.urlempty =
-	      blob.encode(IDENTITY, blob.decode_n(1, BASE64URL, ""));
+	      blob.encode(IDENTITY, blob=blob.decode_n(1, BASE64URL, ""));
 	    set resp.http.nopadempty =
 		blob.encode(IDENTITY,
-				blob.decode_n(0, BASE64URLNOPAD, ""));
+			    blob=blob.decode_n(0, BASE64URLNOPAD, ""));
 	    set resp.http.emptypieces =
 	      blob.encode(IDENTITY,
-	      blob.decode_n(0, BASE64, req.http.unset + "" + req.http.unset
+	      blob=blob.decode_n(0, BASE64, req.http.unset + "" + req.http.unset
 					   + "" + req.http.unset + ""));
 
 	    set resp.http.decenc
 	      = blob.encode(BASE64,
-				blob.decode_n(20, BASE64,
+			    blob=blob.decode_n(20, BASE64,
 						  req.http.foobarbazquux));
 
 	    set resp.http.l = "L";
 	    set resp.http.dec2pieces
-	      = blob.encode(IDENTITY, blob.decode_n(8, BASE64,
+	      = blob.encode(IDENTITY, blob=blob.decode_n(8, BASE64,
 				resp.http.l + "0hlbGxvIHdvcmxkLw=="));
 
 	    set resp.http.pad = "==";
 	    set resp.http.dec3pieces
-	      = blob.encode(IDENTITY, blob.decode_n(12, BASE64,
+	      = blob.encode(IDENTITY, blob=blob.decode_n(12, BASE64,
 				resp.http.l + "0hlbGxvIHdvcmxkLw"
 				+ resp.http.pad));
 
 	    set resp.http.mid1 = "GxvI";
 	    set resp.http.mid2 = "dvcmx";
 	    set resp.http.dec7pieces
-	      = blob.encode(IDENTITY, blob.decode_n(16, BASE64,
+	      = blob.encode(IDENTITY, blob=blob.decode_n(16, BASE64,
 				resp.http.l + "0hlb" + resp.http.mid1
 				+ "H" + resp.http.mid2 + "kLw"
 				+ resp.http.pad));
@@ -109,21 +107,21 @@ varnish v1 -vcl {
 				encoding=IDENTITY);
 
 	    set resp.http.decnopad = blob.encode(IDENTITY,
-				     blob.decode_n(18, BASE64URLNOPAD,
-						       "L0hlbGxvIHdvcmxkLw"));
+				     blob=blob.decode_n(18, BASE64URLNOPAD,
+						        "L0hlbGxvIHdvcmxkLw"));
 
 	    set resp.http.decnopad2pieces
-	      = blob.encode(IDENTITY, blob.decode_n(19, BASE64URLNOPAD,
+	      = blob.encode(IDENTITY, blob=blob.decode_n(19, BASE64URLNOPAD,
 				resp.http.l + "0hlbGxvIHdvcmxkLw"));
 
 	    set resp.http.decnopad6pieces
-	      = blob.encode(IDENTITY, blob.decode_n(18, BASE64URLNOPAD,
+	      = blob.encode(IDENTITY, blob=blob.decode_n(18, BASE64URLNOPAD,
 				resp.http.l + "0hlb" + resp.http.mid1
 				+ "H" + resp.http.mid2 + "kLw"));
 
 	    set resp.http.decnopadlong
 	      = blob.encode(IDENTITY,
-		blob.decode_n(60, BASE64URLNOPAD,
+		blob=blob.decode_n(60, BASE64URLNOPAD,
 		"VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw"
 			       ));
 
@@ -172,16 +170,16 @@ varnish v1 -vcl+backend {
 	  set req.http.foo = "AAA=";
 	  if (req.url == "/base64") {
 		set resp.http.bad64 = blob.encode(IDENTITY,
-		    blob.decode_n(8, BASE64, "-_-_" + req.http.foo));
+		    blob=blob.decode_n(8, BASE64, "-_-_" + req.http.foo));
 	  }
 	  elsif (req.url == "/base64url") {
 		set resp.http.badurl = blob.encode(IDENTITY,
-		    blob.decode_n(8, BASE64URL, "+/+/" + req.http.foo));
+		    blob=blob.decode_n(8, BASE64URL, "+/+/" + req.http.foo));
 	  }
 	  elsif (req.url == "/base64urlnopad") {
 		set resp.http.badpad = blob.encode(IDENTITY,
-		    blob.decode_n(8, BASE64URLNOPAD,
-				      "TWFu" + req.http.foo));
+		    blob=blob.decode_n(8, BASE64URLNOPAD,
+				       "TWFu" + req.http.foo));
 	  }
 	}
 }
diff --git a/bin/varnishtest/tests/m00039.vtc b/bin/varnishtest/tests/m00039.vtc
index 8048ccf..440c7ed 100644
--- a/bin/varnishtest/tests/m00039.vtc
+++ b/bin/varnishtest/tests/m00039.vtc
@@ -21,62 +21,117 @@ varnish v1 -vcl {
 	    set req.http.b64all =
 {"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="};
 
+	    set resp.http.url =
+	      blob.encode(URL, blob=blob.decode(IDENTITY, req.http.pangram));
+
 	    set resp.http.urllc =
-	      blob.encode(URLLC,
-			      blob.decode(IDENTITY, req.http.pangram));
+	      blob.encode(URL, LOWER, blob.decode(IDENTITY, req.http.pangram));
 
 	    set resp.http.urluc =
-	      blob.encode(URLUC,
-			      blob.decode(IDENTITY, req.http.pangram));
+	      blob.encode(URL, UPPER, blob.decode(IDENTITY, req.http.pangram));
+
+	    set resp.http.hobbes =
+	      blob.encode(URL, blob=blob.decode(IDENTITY, req.http.hobbes));
 
 	    set resp.http.hobbeslc =
-	      blob.encode(URLLC, blob.decode(IDENTITY, req.http.hobbes));
+	      blob.encode(URL, LOWER, blob.decode(IDENTITY, req.http.hobbes));
 
 	    set resp.http.hobbesuc =
-	      blob.encode(URLUC, blob.decode(IDENTITY, req.http.hobbes));
+	      blob.encode(URL, UPPER, blob.decode(IDENTITY, req.http.hobbes));
+
+	    set resp.http.umlauts =
+	      blob.encode(URL, blob=blob.decode(IDENTITY, req.http.umlauts));
 
 	    set resp.http.umlautslc =
-	      blob.encode(URLLC,
-			      blob.decode(IDENTITY, req.http.umlauts));
+	      blob.encode(URL, LOWER, blob.decode(IDENTITY, req.http.umlauts));
 
 	    set resp.http.umlautsuc =
-	      blob.encode(URLUC,
-			      blob.decode(IDENTITY, req.http.umlauts));
+	      blob.encode(URL, UPPER, blob.decode(IDENTITY, req.http.umlauts));
+
+	    set resp.http.phk =
+	      blob.encode(URL, blob=blob.decode(IDENTITY, req.http.phkspeak));
 
 	    set resp.http.phklc =
-	      blob.encode(URLLC,
-			     blob.decode(IDENTITY, req.http.phkspeak));
+	      blob.encode(URL, LOWER, blob.decode(IDENTITY, req.http.phkspeak));
 
 	    set resp.http.phkuc =
-	      blob.encode(URLUC,
-			     blob.decode(IDENTITY, req.http.phkspeak));
+	      blob.encode(URL, UPPER, blob.decode(IDENTITY, req.http.phkspeak));
+
+	    set resp.http.utf8 =
+	      blob.encode(URL, blob=blob.decode(IDENTITY, req.http.utf8));
 
 	    set resp.http.utf8lc =
-	      blob.encode(URLLC, blob.decode(IDENTITY, req.http.utf8));
+	      blob.encode(URL, LOWER, blob.decode(IDENTITY, req.http.utf8));
 
 	    set resp.http.utf8uc =
-	      blob.encode(URLUC, blob.decode(IDENTITY, req.http.utf8));
+	      blob.encode(URL, UPPER, blob.decode(IDENTITY, req.http.utf8));
+
+	    set resp.http.all =
+	      blob.encode(URL, blob=blob.decode(BASE64, req.http.b64all));
 
 	    set resp.http.all-lc =
-	      blob.encode(URLLC, blob.decode(BASE64, req.http.b64all));
+	      blob.encode(URL, LOWER, blob.decode(BASE64, req.http.b64all));
 
 	    set resp.http.all-uc =
-	      blob.encode(URLUC, blob.decode(BASE64, req.http.b64all));
+	      blob.encode(URL, UPPER, blob.decode(BASE64, req.http.b64all));
+
+	    set resp.http.empty =
+	      blob.encode(URL, blob=blob.decode(IDENTITY, ""));
 
 	    set resp.http.empty-lc =
-	      blob.encode(URLLC, blob.decode(IDENTITY, ""));
+	      blob.encode(URL, LOWER, blob.decode(IDENTITY, ""));
 
 	    set resp.http.empty-uc =
-	      blob.encode(URLUC, blob.decode(IDENTITY, ""));
+	      blob.encode(URL, UPPER, blob.decode(IDENTITY, ""));
 
 	    set resp.http.urllcparam =
 	      blob.encode(blob=blob.decode(IDENTITY, req.http.pangram),
-			      encoding=URLLC);
+			  encoding=URL, case=LOWER);
 
 	    set resp.http.urlucparam =
 	      blob.encode(blob=blob.decode(IDENTITY, req.http.pangram),
-			      encoding=URLUC);
+			  encoding=URL, case=UPPER);
+	}
+} -start
+
+client c1 {
+	txreq -url "/"
+	rxresp
+	expect resp.http.url == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
+	expect resp.http.urllc == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
+	expect resp.http.urluc == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
+	expect resp.http.hobbes == "Man%20is%20distinguished%2c%20not%20only%20by%20his%20reason%2c%20but%20by%20this%20singular%20passion%20from%20other%20animals%2c%20which%20is%20a%20lust%20of%20the%20mind%2c%20that%20by%20a%20perseverance%20of%20delight%20in%20the%20continued%20and%20indefatigable%20generation%20of%20knowledge%2c%20exceeds%20the%20short%20vehemence%20of%20any%20carnal%20pleasure."
+	expect resp.http.hobbeslc == "Man%20is%20distinguished%2c%20not%20only%20by%20his%20reason%2c%20but%20by%20this%20singular%20passion%20from%20other%20animals%2c%20which%20is%20a%20lust%20of%20the%20mind%2c%20that%20by%20a%20perseverance%20of%20delight%20in%20the%20continued%20and%20indefatigable%20generation%20of%20knowledge%2c%20exceeds%20the%20short%20vehemence%20of%20any%20carnal%20pleasure."
+	expect resp.http.hobbesuc == "Man%20is%20distinguished%2C%20not%20only%20by%20his%20reason%2C%20but%20by%20this%20singular%20passion%20from%20other%20animals%2C%20which%20is%20a%20lust%20of%20the%20mind%2C%20that%20by%20a%20perseverance%20of%20delight%20in%20the%20continued%20and%20indefatigable%20generation%20of%20knowledge%2C%20exceeds%20the%20short%20vehemence%20of%20any%20carnal%20pleasure."
+	expect resp.http.umlauts == "%c3%9cbergr%c3%b6%c3%9fentr%c3%a4ger"
+	expect resp.http.umlautslc == "%c3%9cbergr%c3%b6%c3%9fentr%c3%a4ger"
+	expect resp.http.umlautsuc == "%C3%9Cbergr%C3%B6%C3%9Fentr%C3%A4ger"
+	expect resp.http.phk == "sm%c3%a5b%c3%b8rnsp%c3%a6dagog"
+	expect resp.http.phklc == "sm%c3%a5b%c3%b8rnsp%c3%a6dagog"
+	expect resp.http.phkuc == "sm%C3%A5b%C3%B8rnsp%C3%A6dagog"
+	expect resp.http.utf8 == "%e6%97%a5%e6%89%bc%e8%aa%9e"
+	expect resp.http.utf8lc == "%e6%97%a5%e6%89%bc%e8%aa%9e"
+	expect resp.http.utf8uc == "%E6%97%A5%E6%89%BC%E8%AA%9E"
+	expect resp.http.all == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5b%5c%5d%5e_%60abcdefghijklmnopqrstuvwxyz%7b%7c%7d~%7f%80%81%82%83%84%85%86%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe%ff"
+	expect resp.http.all-lc == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5b%5c%5d%5e_%60abcdefghijklmnopqrstuvwxyz%7b%7c%7d~%7f%80%81%82%83%84%85%86%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe%ff"
+	expect resp.http.all-uc == "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF"
+	expect resp.http.empty == ""
+	expect resp.http.empty-uc == ""
+	expect resp.http.empty-lc == ""
+	expect resp.http.urllcparam == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
+	expect resp.http.urlucparam == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
+} -run
+
+varnish v1 -vcl {
+	import blob;
+	import std;
+	backend b { .host = "${bad_ip}"; }
 
+	sub vcl_recv {
+	  return(synth(200));
+	}
+
+	sub vcl_synth {
 	    set req.http.urllcfoobar = "foo%3abar%3abaz%3aquux";
 	    set req.http.urlucfoobar = "foo%3Abar%3Abaz%3Aquux";
 	    set req.http.urlmixedfoobar = "foo%3Abar%3abaz%3Aquux";
@@ -93,68 +148,68 @@ varnish v1 -vcl {
 
 	    set resp.http.decuc =
 	      blob.encode(IDENTITY,
-			      blob.decode(URL, req.http.urlucfoobar));
+			  blob=blob.decode(URL, req.http.urlucfoobar));
 
 	    set resp.http.declc =
 	      blob.encode(IDENTITY,
-			      blob.decode(URL, req.http.urllcfoobar));
+			  blob=blob.decode(URL, req.http.urllcfoobar));
 
 	    set resp.http.decmixed =
 	      blob.encode(IDENTITY,
-			      blob.decode(URL, req.http.urlmixedfoobar));
+			  blob=blob.decode(URL, req.http.urlmixedfoobar));
 
 	    set resp.http.dechobbesuc =
 	      blob.encode(IDENTITY,
-			      blob.decode(URL, req.http.urlhobbesuc));
+			  blob=blob.decode(URL, req.http.urlhobbesuc));
 
 	    set resp.http.dechobbeslc =
 	      blob.encode(IDENTITY,
-			      blob.decode(URL, req.http.urlhobbeslc));
+			  blob=blob.decode(URL, req.http.urlhobbeslc));
 
 	    set resp.http.decumlautsuc =
 	      blob.encode(IDENTITY,
-			      blob.decode(URL, req.http.urlucumlauts));
+			  blob=blob.decode(URL, req.http.urlucumlauts));
 
 	    set resp.http.decumlautslc =
 	      blob.encode(IDENTITY,
-			      blob.decode(URL, req.http.urllcumlauts));
+			  blob=blob.decode(URL, req.http.urllcumlauts));
 
 	    set resp.http.decphkuc =
 	      blob.encode(IDENTITY,
-			      blob.decode(URL, req.http.urlucphk));
+			  blob=blob.decode(URL, req.http.urlucphk));
 
 	    set resp.http.decphklc =
 	      blob.encode(IDENTITY,
-			      blob.decode(URL, req.http.urllcphk));
+			  blob=blob.decode(URL, req.http.urllcphk));
 
 	    set resp.http.decutf8uc =
 	      blob.encode(IDENTITY,
-			      blob.decode(URL, req.http.urlucutf8));
+			  blob=blob.decode(URL, req.http.urlucutf8));
 
 	    set resp.http.decutf8lc =
 	      blob.encode(IDENTITY,
-			      blob.decode(URL, req.http.urllcutf8));
+			  blob=blob.decode(URL, req.http.urllcutf8));
 
 	    set resp.http.decalluc =
-	      blob.encode(BASE64, blob.decode(URL, req.http.urlalluc));
+	      blob.encode(BASE64, blob=blob.decode(URL, req.http.urlalluc));
 
 	    set resp.http.decalllc =
-	      blob.encode(BASE64, blob.decode(URL, req.http.urlalllc));
+	      blob.encode(BASE64, blob=blob.decode(URL, req.http.urlalllc));
 
 	    set resp.http.decempty =
-	      blob.encode(IDENTITY, blob.decode(URL, ""));
+	      blob.encode(IDENTITY, blob=blob.decode(URL, ""));
 
 	    set resp.http.decemptybyte =
-	      blob.encode(IDENTITY, blob.decode(URL, "%00"));
+	      blob.encode(IDENTITY, blob=blob.decode(URL, "%00"));
 
 	    set resp.http.decemptypieces =
 	      blob.encode(IDENTITY,
-			      blob.decode(URL, req.http.unset + ""
+			  blob=blob.decode(URL, req.http.unset + ""
 						   + req.http.unset + ""));
 
 	    set req.http.part1 = "foo%";
 	    set resp.http.dec2pieces =
-	      blob.encode(IDENTITY, blob.decode(URL, req.http.part1 +
+	      blob.encode(IDENTITY, blob=blob.decode(URL, req.http.part1 +
 			     "20bar%20baz%20quux"));
 
 	    set req.http.part2 = "0quux";
@@ -165,37 +220,21 @@ varnish v1 -vcl {
 			      encoding=IDENTITY);
 
 	    set resp.http.dec3pieces =
-	      blob.encode(IDENTITY, blob.decode(URL, req.http.part1 +
+	      blob.encode(IDENTITY, blob=blob.decode(URL, req.http.part1 +
 			      "20bar%20baz%2" + req.http.part2));
 
 	    set resp.http.decmanypieces =
-	      blob.encode(IDENTITY, blob.decode(URL, "" + req.http.unset
+	      blob.encode(IDENTITY, blob=blob.decode(URL, "" + req.http.unset
 			     + req.http.part1 + req.http.unset + ""
 			     + req.http.unset + "" + "20bar%20baz%2"
 			     + "" + req.http.unset + req.http.part2
 			     + req.http.unset + "" + req.http.unset));
 	}
-} -start
+}
 
 client c1 {
 	txreq -url "/"
 	rxresp
-	expect resp.http.urllc == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
-	expect resp.http.urluc == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
-	expect resp.http.hobbeslc == "Man%20is%20distinguished%2c%20not%20only%20by%20his%20reason%2c%20but%20by%20this%20singular%20passion%20from%20other%20animals%2c%20which%20is%20a%20lust%20of%20the%20mind%2c%20that%20by%20a%20perseverance%20of%20delight%20in%20the%20continued%20and%20indefatigable%20generation%20of%20knowledge%2c%20exceeds%20the%20short%20vehemence%20of%20any%20carnal%20pleasure."
-	expect resp.http.hobbesuc == "Man%20is%20distinguished%2C%20not%20only%20by%20his%20reason%2C%20but%20by%20this%20singular%20passion%20from%20other%20animals%2C%20which%20is%20a%20lust%20of%20the%20mind%2C%20that%20by%20a%20perseverance%20of%20delight%20in%20the%20continued%20and%20indefatigable%20generation%20of%20knowledge%2C%20exceeds%20the%20short%20vehemence%20of%20any%20carnal%20pleasure."
-	expect resp.http.umlautslc == "%c3%9cbergr%c3%b6%c3%9fentr%c3%a4ger"
-	expect resp.http.umlautsuc == "%C3%9Cbergr%C3%B6%C3%9Fentr%C3%A4ger"
-	expect resp.http.phklc == "sm%c3%a5b%c3%b8rnsp%c3%a6dagog"
-	expect resp.http.phkuc == "sm%C3%A5b%C3%B8rnsp%C3%A6dagog"
-	expect resp.http.utf8lc == "%e6%97%a5%e6%89%bc%e8%aa%9e"
-	expect resp.http.utf8uc == "%E6%97%A5%E6%89%BC%E8%AA%9E"
-	expect resp.http.all-lc == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5b%5c%5d%5e_%60abcdefghijklmnopqrstuvwxyz%7b%7c%7d~%7f%80%81%82%83%84%85%86%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe%ff"
-	expect resp.http.all-uc == "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF"
-	expect resp.http.empty-uc == ""
-	expect resp.http.empty-lc == ""
-	expect resp.http.urllcparam == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
-	expect resp.http.urlucparam == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
 	expect resp.http.decuc == "foo:bar:baz:quux"
 	expect resp.http.declc == "foo:bar:baz:quux"
 	expect resp.http.decmixed == "foo:bar:baz:quux"
@@ -231,18 +270,18 @@ varnish v1 -vcl+backend {
 	sub vcl_deliver {
 		if (req.url == "/percent") {
 			set resp.http.bad
-			    = blob.encode(URLUC, blob.decode(URL, "%"));
+			    = blob.encode(URL, UPPER, blob.decode(URL, "%"));
 		}
 		elsif (req.url == "/percent-two") {
-			set resp.http.bad = blob.encode(URLUC,
+			set resp.http.bad = blob.encode(URL, UPPER,
 					    blob.decode(URL, "%2"));
 		}
 		elsif (req.url == "/percent-q") {
-			set resp.http.bad = blob.encode(URLUC,
+			set resp.http.bad = blob.encode(URL, UPPER,
 					    blob.decode(URL, "%q"));
 		}
 		elsif (req.url == "/percent-two-q") {
-			set resp.http.bad = blob.encode(URLUC,
+			set resp.http.bad = blob.encode(URL, UPPER,
 					    blob.decode(URL, "%2q"));
 		}
 	}
diff --git a/bin/varnishtest/tests/m00040.vtc b/bin/varnishtest/tests/m00040.vtc
index b3c87b3..2355ca9 100644
--- a/bin/varnishtest/tests/m00040.vtc
+++ b/bin/varnishtest/tests/m00040.vtc
@@ -25,69 +25,67 @@ varnish v1 -vcl {
 
 	    set resp.http.decuc =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(9, URL, req.http.urlucfoobar));
+			  blob=blob.decode_n(9, URL, req.http.urlucfoobar));
 
 	    set resp.http.declc =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(12, URL, req.http.urllcfoobar));
+			  blob=blob.decode_n(12, URL, req.http.urllcfoobar));
 
 	    set resp.http.dechobbesuc =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(27, URL, req.http.urlhobbesuc));
+			  blob=blob.decode_n(27, URL, req.http.urlhobbesuc));
 
 	    set resp.http.dechobbeslc =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(27, URL, req.http.urlhobbeslc));
+			  blob=blob.decode_n(27, URL, req.http.urlhobbeslc));
 
 	    set resp.http.decumlautsuc =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(17, URL,
-						req.http.urlucumlauts));
+			  blob=blob.decode_n(17, URL, req.http.urlucumlauts));
 
 	    set resp.http.decumlautslc =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(25, URL,
-						req.http.urllcumlauts));
+			  blob=blob.decode_n(25, URL, req.http.urllcumlauts));
 
 	    set resp.http.decphkuc =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(18, URL, req.http.urlucphk));
+			  blob=blob.decode_n(18, URL, req.http.urlucphk));
 
 	    set resp.http.decphklc =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(30, URL, req.http.urllcphk));
+			  blob=blob.decode_n(30, URL, req.http.urllcphk));
 
 	    set resp.http.decutf8uc =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(9, URL, req.http.urlucutf8));
+			  blob=blob.decode_n(9, URL, req.http.urlucutf8));
 
 	    set resp.http.decutf8lc =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(18, URL, req.http.urllcutf8));
+			  blob=blob.decode_n(18, URL, req.http.urllcutf8));
 
 	    set resp.http.decalluc =
-	      blob.encode(HEXLC,
-			      blob.decode_n(252, URL, req.http.urlalluc));
+	      blob.encode(HEX,
+			  blob=blob.decode_n(252, URL, req.http.urlalluc));
 
 	    set resp.http.decalllc =
-	      blob.encode(HEXUC,
-			      blob.decode_n(252, URL, req.http.urlalllc));
+	      blob.encode(HEX, UPPER,
+			  blob.decode_n(252, URL, req.http.urlalllc));
 
 	    set resp.http.decempty =
-	      blob.encode(IDENTITY, blob.decode_n(10, URL, ""));
+	      blob.encode(IDENTITY, blob=blob.decode_n(10, URL, ""));
 
 	    set resp.http.decemptybyte =
-	      blob.encode(IDENTITY, blob.decode_n(3, URL, "%00"));
+	      blob.encode(IDENTITY, blob=blob.decode_n(3, URL, "%00"));
 
 	    set resp.http.decemptypieces =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(1, URL, req.http.unset + ""
+			  blob=blob.decode_n(1, URL, req.http.unset + ""
 							+ req.http.unset + ""));
 
 	    set req.http.part1 = "foo%";
 	    set resp.http.dec2pieces =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(6, URL, req.http.part1 +
+			  blob=blob.decode_n(6, URL, req.http.part1 +
 							"20bar%20baz%20quux"));
 
 	    set req.http.part2 = "0quux";
@@ -99,13 +97,13 @@ varnish v1 -vcl {
 
 	    set resp.http.dec3pieces =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(18, URL, req.http.part1
+			  blob=blob.decode_n(18, URL, req.http.part1
 						+ "20bar%20baz%2"
 						+ req.http.part2));
 
 	    set resp.http.decmanypieces =
 	      blob.encode(IDENTITY,
-			      blob.decode_n(24, URL, "" + req.http.unset
+			      blob=blob.decode_n(24, URL, "" + req.http.unset
 			      + req.http.part1 + req.http.unset + ""
 			      + req.http.unset + "" + "20bar%20baz%2"
 			      + "" + req.http.unset + req.http.part2
@@ -149,20 +147,20 @@ varnish v1 -vcl+backend {
 
 	sub vcl_deliver {
 		if (req.url == "/percent") {
-			set resp.http.bad = blob.encode(URLUC,
+			set resp.http.bad = blob.encode(URL, UPPER,
 					    blob.decode_n(1, URL, "%20"));
 		}
 		elsif (req.url == "/percent-two") {
-			set resp.http.bad = blob.encode(URLUC,
+			set resp.http.bad = blob.encode(URL, UPPER,
 					    blob.decode_n(2, URL, "%20"));
 		}
 		elsif (req.url == "/comma") {
-			set resp.http.good = blob.encode(IDENTITY,
-					    blob.decode_n(3, URL, "%2c%q"));
+			set resp.http.good = blob.encode(IDENTITY, blob=
+					     blob.decode_n(3, URL, "%2c%q"));
 		}
 		elsif (req.url == "/colon") {
-			set resp.http.good = blob.encode(IDENTITY,
-					   blob.decode_n(3, URL, "%3a%2q"));
+			set resp.http.good = blob.encode(IDENTITY, blob=
+					     blob.decode_n(3, URL, "%3a%2q"));
 		}
 	}
 }
diff --git a/bin/varnishtest/tests/m00041.vtc b/bin/varnishtest/tests/m00041.vtc
index c350ee1..cfed6ae 100644
--- a/bin/varnishtest/tests/m00041.vtc
+++ b/bin/varnishtest/tests/m00041.vtc
@@ -33,97 +33,186 @@ varnish v1 -arg "-p workspace_client=256k" -vcl {
 	    = blob.transcode(encoded=req.http.hobbes, encoding=BASE64);
 
 	  set resp.http.id2b64nopad
-	    = blob.transcode(IDENTITY, BASE64URLNOPAD, req.http.hobbes);
+	    = blob.transcode(IDENTITY, BASE64URLNOPAD, encoded=req.http.hobbes);
+
+	  set resp.http.id2hex
+	    = blob.transcode(IDENTITY, HEX, encoded=req.http.hobbes);
 
 	  set resp.http.id2hexuc
-	    = blob.transcode(IDENTITY, HEXUC, req.http.hobbes);
+	    = blob.transcode(IDENTITY, HEX, UPPER, req.http.hobbes);
 
 	  set resp.http.id2hexlc
-	    = blob.transcode(IDENTITY, HEXLC, req.http.hobbes);
+	    = blob.transcode(IDENTITY, HEX, LOWER, req.http.hobbes);
+
+	  set resp.http.id2url
+	    = blob.transcode(IDENTITY, URL, encoded=req.http.foobar);
 
 	  set resp.http.id2urluc
-	    = blob.transcode(IDENTITY, URLUC, req.http.foobar);
+	    = blob.transcode(IDENTITY, URL, UPPER, req.http.foobar);
 
 	  set resp.http.id2urllc
-	    = blob.transcode(IDENTITY, URLLC, req.http.foobar);
+	    = blob.transcode(IDENTITY, URL, LOWER, req.http.foobar);
 
 	  set resp.http.b642id
-	    = blob.transcode(BASE64, IDENTITY, req.http.hobbesb64);
+	    = blob.transcode(BASE64, IDENTITY, encoded=req.http.hobbesb64);
 
 	  set resp.http.hex2id
-	    = blob.transcode(HEX, IDENTITY, req.http.hexhobbes);
+	    = blob.transcode(HEX, IDENTITY, encoded=req.http.hexhobbes);
 
 	  set resp.http.hexalldown2b64
-	    = blob.transcode(HEX, BASE64, req.http.hexalldown);
+	    = blob.transcode(HEX, BASE64, encoded=req.http.hexalldown);
 
 	  set resp.http.hexalldown2b64url
-	    = blob.transcode(HEX, BASE64URL, req.http.hexalldown);
+	    = blob.transcode(HEX, BASE64URL, encoded=req.http.hexalldown);
 
 	  set resp.http.hexalldown2b64nopad
-	    = blob.transcode(HEX, BASE64URLNOPAD, req.http.hexalldown);
+	    = blob.transcode(HEX, BASE64URLNOPAD, encoded=req.http.hexalldown);
 
 	  set resp.http.hexallup2b64
-	    = blob.transcode(HEX, BASE64, req.http.hexallup);
+	    = blob.transcode(HEX, BASE64, encoded=req.http.hexallup);
 
 	  set resp.http.hexallup2b64url
-	    = blob.transcode(HEX, BASE64URL, req.http.hexallup);
+	    = blob.transcode(HEX, BASE64URL, encoded=req.http.hexallup);
 
 	  set resp.http.hexallup2b64nopad
-	    = blob.transcode(HEX, BASE64URLNOPAD, req.http.hexallup);
+	    = blob.transcode(HEX, BASE64URLNOPAD, encoded=req.http.hexallup);
+
+	  set resp.http.hexalldown2url
+	    = blob.transcode(HEX, URL, encoded=req.http.hexalldown);
 
 	  set resp.http.hexalldown2urluc
-	    = blob.transcode(HEX, URLUC, req.http.hexalldown);
+	    = blob.transcode(HEX, URL, UPPER, req.http.hexalldown);
 
 	  set resp.http.hexalldown2urllc
-	    = blob.transcode(HEX, URLLC, req.http.hexalldown);
+	    = blob.transcode(HEX, URL, LOWER, req.http.hexalldown);
+
+	  set resp.http.hexallup2url
+	    = blob.transcode(HEX, URL, encoded=req.http.hexallup);
 
 	  set resp.http.hexallup2urluc
-	    = blob.transcode(HEX, URLUC, req.http.hexallup);
+	    = blob.transcode(HEX, URL, UPPER, req.http.hexallup);
 
 	  set resp.http.hexallup2urllc
-	    = blob.transcode(HEX, URLLC, req.http.hexallup);
+	    = blob.transcode(HEX, URL, LOWER, req.http.hexallup);
+
+	}
+} -start
+
+client c1 {
+	txreq
+	rxresp
+	expect resp.http.id2id == "Hello world"
+	expect resp.http.id2b64 == "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="
+	expect resp.http.id2b64nopad == "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4"
+	expect resp.http.id2hex == "4d616e2069732064697374696e677569736865642c206e6f74206f6e6c792062792068697320726561736f6e2c2062757420627920746869732073696e67756c61722070617373696f6e2066726f6d206f7468657220616e696d616c732c2077686963682069732061206c757374206f6620746865206d696e642c20746861742062792061207065727365766572616e6365206f662064656c6967687420696e2074686520636f6e74696e75656420616e6420696e6465666174696761626c652067656e65726174696f6e206f66206b6e6f776c656467652c2065786365656473207468652073686f727420766568656d656e6365206f6620616e79206361726e616c20706c6561737572652e"
+	expect resp.http.id2hexuc == "4D616E2069732064697374696E677569736865642C206E6F74206F6E6C792062792068697320726561736F6E2C2062757420627920746869732073696E67756C61722070617373696F6E2066726F6D206F7468657220616E696D616C732C2077686963682069732061206C757374206F6620746865206D696E642C20746861742062792061207065727365766572616E6365206F662064656C6967687420696E2074686520636F6E74696E75656420616E6420696E6465666174696761626C652067656E65726174696F6E206F66206B6E6F776C656467652C2065786365656473207468652073686F727420766568656D656E6365206F6620616E79206361726E616C20706C6561737572652E"
+	expect resp.http.id2hexlc == resp.http.id2hex
+	expect resp.http.id2url == "foo%3abar%3abaz%3aquux"
+	expect resp.http.id2urluc == "foo%3Abar%3Abaz%3Aquux"
+	expect resp.http.id2urllc == resp.http.id2url
+	expect resp.http.b642id == "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."
+	expect resp.http.hex2id == "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."
+	expect resp.http.hexalldown2b64 == "//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAA=="
+	expect resp.http.hexalldown2b64url == "__79_Pv6-fj39vX08_Lx8O_u7ezr6uno5-bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL--vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI-OjYyLiomIh4aFhIOCgYB_fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAA=="
+	expect resp.http.hexalldown2b64nopad == "__79_Pv6-fj39vX08_Lx8O_u7ezr6uno5-bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL--vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI-OjYyLiomIh4aFhIOCgYB_fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAA"
+	expect resp.http.hexallup2b64 == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="
+	expect resp.http.hexallup2b64url == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w=="
+	expect resp.http.hexallup2b64nopad == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w"
+	expect resp.http.hexalldown2url == "%ff%fe%fd%fc%fb%fa%f9%f8%f7%f6%f5%f4%f3%f2%f1%f0%ef%ee%ed%ec%eb%ea%e9%e8%e7%e6%e5%e4%e3%e2%e1%e0%df%de%dd%dc%db%da%d9%d8%d7%d6%d5%d4%d3%d2%d1%d0%cf%ce%cd%cc%cb%ca%c9%c8%c7%c6%c5%c4%c3%c2%c1%c0%bf%be%bd%bc%bb%ba%b9%b8%b7%b6%b5%b4%b3%b2%b1%b0%af%ae%ad%ac%ab%aa%a9%a8%a7%a6%a5%a4%a3%a2%a1%a0%9f%9e%9d%9c%9b%9a%99%98%97%96%95%94%93%92%91%90%8f%8e%8d%8c%8b%8a%89%88%87%86%85%84%83%82%81%80%7f~%7d%7c%7bzyxwvutsrqponmlkjihgfedcba%60_%5e%5d%5c%5bZYXWVUTSRQPONMLKJIHGFEDCBA%40%3f%3e%3d%3c%3b%3a9876543210%2f.-%2c%2b%2a%29%28%27%26%25%24%23%22%21%20%1f%1e%1d%1c%1b%1a%19%18%17%16%15%14%13%12%11%10%0f%0e%0d%0c%0b%0a%09%08%07%06%05%04%03%02%01%00"
+	expect resp.http.hexalldown2urluc == "%FF%FE%FD%FC%FB%FA%F9%F8%F7%F6%F5%F4%F3%F2%F1%F0%EF%EE%ED%EC%EB%EA%E9%E8%E7%E6%E5%E4%E3%E2%E1%E0%DF%DE%DD%DC%DB%DA%D9%D8%D7%D6%D5%D4%D3%D2%D1%D0%CF%CE%CD%CC%CB%CA%C9%C8%C7%C6%C5%C4%C3%C2%C1%C0%BF%BE%BD%BC%BB%BA%B9%B8%B7%B6%B5%B4%B3%B2%B1%B0%AF%AE%AD%AC%AB%AA%A9%A8%A7%A6%A5%A4%A3%A2%A1%A0%9F%9E%9D%9C%9B%9A%99%98%97%96%95%94%93%92%91%90%8F%8E%8D%8C%8B%8A%89%88%87%86%85%84%83%82%81%80%7F~%7D%7C%7Bzyxwvutsrqponmlkjihgfedcba%60_%5E%5D%5C%5BZYXWVUTSRQPONMLKJIHGFEDCBA%40%3F%3E%3D%3C%3B%3A9876543210%2F.-%2C%2B%2A%29%28%27%26%25%24%23%22%21%20%1F%1E%1D%1C%1B%1A%19%18%17%16%15%14%13%12%11%10%0F%0E%0D%0C%0B%0A%09%08%07%06%05%04%03%02%01%00"
+	expect resp.http.hexalldown2urllc == resp.http.hexalldown2url
+	expect resp.http.hexallup2url == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5b%5c%5d%5e_%60abcdefghijklmnopqrstuvwxyz%7b%7c%7d~%7f%80%81%82%83%84%85%86%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe%ff"
+	expect resp.http.hexallup2urluc == "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF"
+	expect resp.http.hexallup2urllc == resp.http.hexallup2url
+} -run
+
+varnish v1 -vcl {
+	import blob;
+	import std;
+	backend b { .host = "${bad_ip}"; }
+
+	sub vcl_recv {
+	  return(synth(200));
+	}
+
+	sub vcl_synth {
+	    set req.http.foobar = "foo:bar:baz:quux";
+	    set req.http.hobbes =
+{"Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."};
+	    set req.http.hobbesb64 =
+{"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="};
+	    set req.http.hexhobbes = "4d616e2069732064697374696e677569736865642c206e6f74206f6e6c792062792068697320726561736f6e2c2062757420627920746869732073696e67756c61722070617373696f6e2066726f6d206f7468657220616e696d616c732c2077686963682069732061206c757374206f6620746865206d696e642c20746861742062792061207065727365766572616e6365206f662064656c6967687420696e2074686520636f6e74696e75656420616e6420696e6465666174696761626c652067656e65726174696f6e206f66206b6e6f776c656467652c2065786365656473207468652073686f727420766568656d656e6365206f6620616e79206361726e616c20706c6561737572652e";
+	    set req.http.hexalldown =
+{"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a09f9e9d9c9b9a999897969594939291908f8e8d8c8b8a898887868584838281807f7e7d7c7b7a797877767574737271706f6e6d6c6b6a696867666564636261605f5e5d5c5b5a595857565554535251504f4e4d4c4b4a494847464544434241403f3e3d3c3b3a393837363534333231302f2e2d2c2b2a292827262524232221201f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100"};
+	    set req.http.hexallup =
+{"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"};
+	    set req.http.b64all =
+{"AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZaaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzz0000111122223333444455556666777788889999++++////"};
+	    set req.http.b64allurl =
+{"AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZaaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzz0000111122223333444455556666777788889999----____"};
+
+	  set resp.http.b64all2hex
+	    = blob.transcode(BASE64, HEX, encoded=req.http.b64all);
 
 	  set resp.http.b64all2hexuc
-	    = blob.transcode(BASE64, HEXUC, req.http.b64all);
+	    = blob.transcode(BASE64, HEX, UPPER, req.http.b64all);
 
 	  set resp.http.b64all2hexlc
-	    = blob.transcode(BASE64, HEXLC, req.http.b64all);
+	    = blob.transcode(BASE64, HEX, LOWER, req.http.b64all);
+
+	  set resp.http.b64allurl2hex
+	    = blob.transcode(BASE64URL, HEX, encoded=req.http.b64allurl);
 
 	  set resp.http.b64allurl2hexuc
-	    = blob.transcode(BASE64URL, HEXUC, req.http.b64allurl);
+	    = blob.transcode(BASE64URL, HEX, UPPER, req.http.b64allurl);
 
 	  set resp.http.b64allurl2hexlc
-	    = blob.transcode(BASE64URL, HEXLC, req.http.b64allurl);
+	    = blob.transcode(BASE64URL, HEX, LOWER, req.http.b64allurl);
+
+	  set resp.http.b64all2url
+	    = blob.transcode(BASE64, URL, encoded=req.http.b64all);
 
 	  set resp.http.b64all2urluc
-	    = blob.transcode(BASE64, URLUC, req.http.b64all);
+	    = blob.transcode(BASE64, URL, UPPER, req.http.b64all);
 
 	  set resp.http.b64all2urllc
-	    = blob.transcode(BASE64, URLLC, req.http.b64all);
+	    = blob.transcode(BASE64, URL, LOWER, req.http.b64all);
+
+	  set resp.http.b64allurl2url
+	    = blob.transcode(BASE64URL, URL, encoded=req.http.b64allurl);
 
 	  set resp.http.b64allurl2urluc
-	    = blob.transcode(BASE64URL, URLUC, req.http.b64allurl);
+	    = blob.transcode(BASE64URL, URL, UPPER, req.http.b64allurl);
 
 	  set resp.http.b64allurl2urllc
-	    = blob.transcode(BASE64URL, URLLC, req.http.b64allurl);
+	    = blob.transcode(BASE64URL, URL, LOWER, req.http.b64allurl);
+
+	  set resp.http.hexuc2hex
+	    = blob.transcode(HEX, HEX, encoded="0123456789ABCDEF");
 
 	  set resp.http.hexuc2hexuc
-	    = blob.transcode(HEX, HEXUC, "0123456789ABCDEF");
+	    = blob.transcode(HEX, HEX, UPPER, "0123456789ABCDEF");
 
 	  set resp.http.hexlc2hexlc
-	    = blob.transcode(HEX, HEXLC, "0123456789abcdef");
+	    = blob.transcode(HEX, HEX, LOWER, "0123456789abcdef");
+
+	  set resp.http.hexlc2hex
+	    = blob.transcode(HEX, HEX, encoded="0123456789abcdef");
 
 	  set resp.http.hexuc2hexlc
-	    = blob.transcode(HEX, HEXLC, "0123456789ABCDEF");
+	    = blob.transcode(HEX, HEX, LOWER, "0123456789ABCDEF");
 
 	  set resp.http.hexlc2hexuc
-	    = blob.transcode(HEX, HEXUC, "0123456789abcdef");
+	    = blob.transcode(HEX, HEX, UPPER, "0123456789abcdef");
+
+	  set resp.http.hexmix2hex
+	    = blob.transcode(HEX, HEX, encoded="0123456789ABCdef");
 
 	  set resp.http.hexmix2hexuc
-	    = blob.transcode(HEX, HEXUC, "0123456789ABCdef");
+	    = blob.transcode(HEX, HEX, UPPER, "0123456789ABCdef");
 
 	  set resp.http.hexmix2hexlc
-	    = blob.transcode(HEX, HEXLC, "0123456789abcDEF");
+	    = blob.transcode(HEX, HEX, LOWER, "0123456789abcDEF");
 
 	  set req.http.hexpart1 = "01234567";
 	  set req.http.hexpart2 = "89abcdef";
@@ -132,62 +221,50 @@ varnish v1 -arg "-p workspace_client=256k" -vcl {
 				 + req.http.unset + "" + req.http.hexpart1
 				 + "" + req.http.unset + "" + req.http.unset
 				 + req.http.hexpart2, decoding=HEX,
-				 encoding=HEXUC);
+				 encoding=HEX, case=UPPER);
 
 	  set resp.http.b642b64
-	    = blob.transcode(BASE64, BASE64,
+	    = blob.transcode(BASE64, BASE64, encoded=
 				 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
 				 + "ghijklmnopqrstuvwxyz0123456789+/");
 
 	  set resp.http.b64url2b64url =
-	    blob.transcode(BASE64URL, BASE64URL,
+	    blob.transcode(BASE64URL, BASE64URL, encoded=
 			       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
 			       + "ghijklmnopqrstuvwxyz0123456789-_");
 
 	  set resp.http.b64urlnopad2b64urlnopad =
-	    blob.transcode(BASE64URLNOPAD, BASE64URLNOPAD,
+	    blob.transcode(BASE64URLNOPAD, BASE64URLNOPAD, encoded=
 			       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
 			       + "ghijklmnopqrstuvwxyz0123456789-_");
 
 	}
-} -start
+}
 
 client c1 {
 	txreq
 	rxresp
-	expect resp.http.id2id == "Hello world"
-	expect resp.http.id2b64 == "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="
-	expect resp.http.id2b64nopad == "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4"
-	expect resp.http.id2hexuc == "4D616E2069732064697374696E677569736865642C206E6F74206F6E6C792062792068697320726561736F6E2C2062757420627920746869732073696E67756C61722070617373696F6E2066726F6D206F7468657220616E696D616C732C2077686963682069732061206C757374206F6620746865206D696E642C20746861742062792061207065727365766572616E6365206F662064656C6967687420696E2074686520636F6E74696E75656420616E6420696E6465666174696761626C652067656E65726174696F6E206F66206B6E6F776C656467652C2065786365656473207468652073686F727420766568656D656E6365206F6620616E79206361726E616C20706C6561737572652E"
-	expect resp.http.id2hexlc == "4d616e2069732064697374696e677569736865642c206e6f74206f6e6c792062792068697320726561736f6e2c2062757420627920746869732073696e67756c61722070617373696f6e2066726f6d206f7468657220616e696d616c732c2077686963682069732061206c757374206f6620746865206d696e642c20746861742062792061207065727365766572616e6365206f662064656c6967687420696e2074686520636f6e74696e75656420616e6420696e6465666174696761626c652067656e65726174696f6e206f66206b6e6f776c656467652c2065786365656473207468652073686f727420766568656d656e6365206f6620616e79206361726e616c20706c6561737572652e"
-	expect resp.http.id2urluc == "foo%3Abar%3Abaz%3Aquux"
-	expect resp.http.id2urllc == "foo%3abar%3abaz%3aquux"
-	expect resp.http.b642id == "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."
-	expect resp.http.hex2id == "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."
-	expect resp.http.hexalldown2b64 == "//79/Pv6+fj39vX08/Lx8O/u7ezr6uno5+bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL++vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI+OjYyLiomIh4aFhIOCgYB/fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAA=="
-	expect resp.http.hexalldown2b64url == "__79_Pv6-fj39vX08_Lx8O_u7ezr6uno5-bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL--vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI-OjYyLiomIh4aFhIOCgYB_fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAA=="
-	expect resp.http.hexalldown2b64nopad == "__79_Pv6-fj39vX08_Lx8O_u7ezr6uno5-bl5OPi4eDf3t3c29rZ2NfW1dTT0tHQz87NzMvKycjHxsXEw8LBwL--vby7urm4t7a1tLOysbCvrq2sq6qpqKempaSjoqGgn56dnJuamZiXlpWUk5KRkI-OjYyLiomIh4aFhIOCgYB_fn18e3p5eHd2dXRzcnFwb25tbGtqaWhnZmVkY2JhYF9eXVxbWllYV1ZVVFNSUVBPTk1MS0pJSEdGRURDQkFAPz49PDs6OTg3NjU0MzIxMC8uLSwrKikoJyYlJCMiISAfHh0cGxoZGBcWFRQTEhEQDw4NDAsKCQgHBgUEAwIBAA"
-	expect resp.http.hexallup2b64 == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="
-	expect resp.http.hexallup2b64url == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w=="
-	expect resp.http.hexallup2b64nopad == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w"
-	expect resp.http.hexalldown2urluc == "%FF%FE%FD%FC%FB%FA%F9%F8%F7%F6%F5%F4%F3%F2%F1%F0%EF%EE%ED%EC%EB%EA%E9%E8%E7%E6%E5%E4%E3%E2%E1%E0%DF%DE%DD%DC%DB%DA%D9%D8%D7%D6%D5%D4%D3%D2%D1%D0%CF%CE%CD%CC%CB%CA%C9%C8%C7%C6%C5%C4%C3%C2%C1%C0%BF%BE%BD%BC%BB%BA%B9%B8%B7%B6%B5%B4%B3%B2%B1%B0%AF%AE%AD%AC%AB%AA%A9%A8%A7%A6%A5%A4%A3%A2%A1%A0%9F%9E%9D%9C%9B%9A%99%98%97%96%95%94%93%92%91%90%8F%8E%8D%8C%8B%8A%89%88%87%86%85%84%83%82%81%80%7F~%7D%7C%7Bzyxwvutsrqponmlkjihgfedcba%60_%5E%5D%5C%5BZYXWVUTSRQPONMLKJIHGFEDCBA%40%3F%3E%3D%3C%3B%3A9876543210%2F.-%2C%2B%2A%29%28%27%26%25%24%23%22%21%20%1F%1E%1D%1C%1B%1A%19%18%17%16%15%14%13%12%11%10%0F%0E%0D%0C%0B%0A%09%08%07%06%05%04%03%02%01%00"
-	expect resp.http.hexalldown2urllc == "%ff%fe%fd%fc%fb%fa%f9%f8%f7%f6%f5%f4%f3%f2%f1%f0%ef%ee%ed%ec%eb%ea%e9%e8%e7%e6%e5%e4%e3%e2%e1%e0%df%de%dd%dc%db%da%d9%d8%d7%d6%d5%d4%d3%d2%d1%d0%cf%ce%cd%cc%cb%ca%c9%c8%c7%c6%c5%c4%c3%c2%c1%c0%bf%be%bd%bc%bb%ba%b9%b8%b7%b6%b5%b4%b3%b2%b1%b0%af%ae%ad%ac%ab%aa%a9%a8%a7%a6%a5%a4%a3%a2%a1%a0%9f%9e%9d%9c%9b%9a%99%98%97%96%95%94%93%92%91%90%8f%8e%8d%8c%8b%8a%89%88%87%86%85%84%83%82%81%80%7f~%7d%7c%7bzyxwvutsrqponmlkjihgfedcba%60_%5e%5d%5c%5bZYXWVUTSRQPONMLKJIHGFEDCBA%40%3f%3e%3d%3c%3b%3a9876543210%2f.-%2c%2b%2a%29%28%27%26%25%24%23%22%21%20%1f%1e%1d%1c%1b%1a%19%18%17%16%15%14%13%12%11%10%0f%0e%0d%0c%0b%0a%09%08%07%06%05%04%03%02%01%00"
-	expect resp.http.hexallup2urluc == "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF"
-	expect resp.http.hexallup2urllc == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5b%5c%5d%5e_%60abcdefghijklmnopqrstuvwxyz%7b%7c%7d~%7f%80%81%82%83%84%85%86%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe%ff"
+	expect resp.http.b64all2hex == "0000000410410820820c30c31041041451451861861c71c720820824924928a28a2cb2cb30c30c34d34d38e38e3cf3cf4104104514514924924d34d35145145555555965965d75d761861865965969a69a6db6db71c71c75d75d79e79e7df7df8208208618618a28a28e38e39249249659659a69a69e79e7a28a28a69a69aaaaaaaebaebb2cb2cb6db6dbaebaebefbefc30c30c71c71cb2cb2cf3cf3d34d34d75d75db6db6df7df7e38e38e79e79ebaebaefbefbf3cf3cf7df7dfbefbeffffff"
 	expect resp.http.b64all2hexuc == "0000000410410820820C30C31041041451451861861C71C720820824924928A28A2CB2CB30C30C34D34D38E38E3CF3CF4104104514514924924D34D35145145555555965965D75D761861865965969A69A6DB6DB71C71C75D75D79E79E7DF7DF8208208618618A28A28E38E39249249659659A69A69E79E7A28A28A69A69AAAAAAAEBAEBB2CB2CB6DB6DBAEBAEBEFBEFC30C30C71C71CB2CB2CF3CF3D34D34D75D75DB6DB6DF7DF7E38E38E79E79EBAEBAEFBEFBF3CF3CF7DF7DFBEFBEFFFFFF"
-	expect resp.http.b64all2hexlc == "0000000410410820820c30c31041041451451861861c71c720820824924928a28a2cb2cb30c30c34d34d38e38e3cf3cf4104104514514924924d34d35145145555555965965d75d761861865965969a69a6db6db71c71c75d75d79e79e7df7df8208208618618a28a28e38e39249249659659a69a69e79e7a28a28a69a69aaaaaaaebaebb2cb2cb6db6dbaebaebefbefc30c30c71c71cb2cb2cf3cf3d34d34d75d75db6db6df7df7e38e38e79e79ebaebaefbefbf3cf3cf7df7dfbefbeffffff"
+	expect resp.http.b64all2hexlc == resp.http.b64all2hex
+	expect resp.http.b64allurl2hex == "0000000410410820820c30c31041041451451861861c71c720820824924928a28a2cb2cb30c30c34d34d38e38e3cf3cf4104104514514924924d34d35145145555555965965d75d761861865965969a69a6db6db71c71c75d75d79e79e7df7df8208208618618a28a28e38e39249249659659a69a69e79e7a28a28a69a69aaaaaaaebaebb2cb2cb6db6dbaebaebefbefc30c30c71c71cb2cb2cf3cf3d34d34d75d75db6db6df7df7e38e38e79e79ebaebaefbefbf3cf3cf7df7dfbefbeffffff"
 	expect resp.http.b64allurl2hexuc == "0000000410410820820C30C31041041451451861861C71C720820824924928A28A2CB2CB30C30C34D34D38E38E3CF3CF4104104514514924924D34D35145145555555965965D75D761861865965969A69A6DB6DB71C71C75D75D79E79E7DF7DF8208208618618A28A28E38E39249249659659A69A69E79E7A28A28A69A69AAAAAAAEBAEBB2CB2CB6DB6DBAEBAEBEFBEFC30C30C71C71CB2CB2CF3CF3D34D34D75D75DB6DB6DF7DF7E38E38E79E79EBAEBAEFBEFBF3CF3CF7DF7DFBEFBEFFFFFF"
-	expect resp.http.b64allurl2hexlc == "0000000410410820820c30c31041041451451861861c71c720820824924928a28a2cb2cb30c30c34d34d38e38e3cf3cf4104104514514924924d34d35145145555555965965d75d761861865965969a69a6db6db71c71c75d75d79e79e7df7df8208208618618a28a28e38e39249249659659a69a69e79e7a28a28a69a69aaaaaaaebaebb2cb2cb6db6dbaebaebefbefc30c30c71c71cb2cb2cf3cf3d34d34d75d75db6db6df7df7e38e38e79e79ebaebaefbefbf3cf3cf7df7dfbefbeffffff"
+	expect resp.http.b64allurl2hexlc == resp.http.b64allurl2hex
+	expect resp.http.b64all2url == "%00%00%00%04%10A%08%20%82%0c0%c3%10A%04%14QE%18a%86%1cq%c7%20%82%08%24%92I%28%a2%8a%2c%b2%cb0%c3%0c4%d3M8%e3%8e%3c%f3%cfA%04%10E%14QI%24%92M4%d3QE%14UUUYe%96%5du%d7a%86%18e%96Yi%a6%9am%b6%dbq%c7%1cu%d7%5dy%e7%9e%7d%f7%df%82%08%20%86%18a%8a%28%a2%8e8%e3%92I%24%96Ye%9ai%a6%9ey%e7%a2%8a%28%a6%9ai%aa%aa%aa%ae%ba%eb%b2%cb%2c%b6%dbm%ba%eb%ae%be%fb%ef%c3%0c0%c7%1cq%cb%2c%b2%cf%3c%f3%d3M4%d7%5du%dbm%b6%df%7d%f7%e3%8e8%e7%9ey%eb%ae%ba%ef%be%fb%f3%cf%3c%f7%df%7d%fb%ef%be%ff%ff%ff"
 	expect resp.http.b64all2urluc == "%00%00%00%04%10A%08%20%82%0C0%C3%10A%04%14QE%18a%86%1Cq%C7%20%82%08%24%92I%28%A2%8A%2C%B2%CB0%C3%0C4%D3M8%E3%8E%3C%F3%CFA%04%10E%14QI%24%92M4%D3QE%14UUUYe%96%5Du%D7a%86%18e%96Yi%A6%9Am%B6%DBq%C7%1Cu%D7%5Dy%E7%9E%7D%F7%DF%82%08%20%86%18a%8A%28%A2%8E8%E3%92I%24%96Ye%9Ai%A6%9Ey%E7%A2%8A%28%A6%9Ai%AA%AA%AA%AE%BA%EB%B2%CB%2C%B6%DBm%BA%EB%AE%BE%FB%EF%C3%0C0%C7%1Cq%CB%2C%B2%CF%3C%F3%D3M4%D7%5Du%DBm%B6%DF%7D%F7%E3%8E8%E7%9Ey%EB%AE%BA%EF%BE%FB%F3%CF%3C%F7%DF%7D%FB%EF%BE%FF%FF%FF"
-	expect resp.http.b64all2urllc == "%00%00%00%04%10A%08%20%82%0c0%c3%10A%04%14QE%18a%86%1cq%c7%20%82%08%24%92I%28%a2%8a%2c%b2%cb0%c3%0c4%d3M8%e3%8e%3c%f3%cfA%04%10E%14QI%24%92M4%d3QE%14UUUYe%96%5du%d7a%86%18e%96Yi%a6%9am%b6%dbq%c7%1cu%d7%5dy%e7%9e%7d%f7%df%82%08%20%86%18a%8a%28%a2%8e8%e3%92I%24%96Ye%9ai%a6%9ey%e7%a2%8a%28%a6%9ai%aa%aa%aa%ae%ba%eb%b2%cb%2c%b6%dbm%ba%eb%ae%be%fb%ef%c3%0c0%c7%1cq%cb%2c%b2%cf%3c%f3%d3M4%d7%5du%dbm%b6%df%7d%f7%e3%8e8%e7%9ey%eb%ae%ba%ef%be%fb%f3%cf%3c%f7%df%7d%fb%ef%be%ff%ff%ff"
+	expect resp.http.b64all2urllc == resp.http.b64all2url
+	expect resp.http.b64allurl2url == "%00%00%00%04%10A%08%20%82%0c0%c3%10A%04%14QE%18a%86%1cq%c7%20%82%08%24%92I%28%a2%8a%2c%b2%cb0%c3%0c4%d3M8%e3%8e%3c%f3%cfA%04%10E%14QI%24%92M4%d3QE%14UUUYe%96%5du%d7a%86%18e%96Yi%a6%9am%b6%dbq%c7%1cu%d7%5dy%e7%9e%7d%f7%df%82%08%20%86%18a%8a%28%a2%8e8%e3%92I%24%96Ye%9ai%a6%9ey%e7%a2%8a%28%a6%9ai%aa%aa%aa%ae%ba%eb%b2%cb%2c%b6%dbm%ba%eb%ae%be%fb%ef%c3%0c0%c7%1cq%cb%2c%b2%cf%3c%f3%d3M4%d7%5du%dbm%b6%df%7d%f7%e3%8e8%e7%9ey%eb%ae%ba%ef%be%fb%f3%cf%3c%f7%df%7d%fb%ef%be%ff%ff%ff"
 	expect resp.http.b64allurl2urluc == "%00%00%00%04%10A%08%20%82%0C0%C3%10A%04%14QE%18a%86%1Cq%C7%20%82%08%24%92I%28%A2%8A%2C%B2%CB0%C3%0C4%D3M8%E3%8E%3C%F3%CFA%04%10E%14QI%24%92M4%D3QE%14UUUYe%96%5Du%D7a%86%18e%96Yi%A6%9Am%B6%DBq%C7%1Cu%D7%5Dy%E7%9E%7D%F7%DF%82%08%20%86%18a%8A%28%A2%8E8%E3%92I%24%96Ye%9Ai%A6%9Ey%E7%A2%8A%28%A6%9Ai%AA%AA%AA%AE%BA%EB%B2%CB%2C%B6%DBm%BA%EB%AE%BE%FB%EF%C3%0C0%C7%1Cq%CB%2C%B2%CF%3C%F3%D3M4%D7%5Du%DBm%B6%DF%7D%F7%E3%8E8%E7%9Ey%EB%AE%BA%EF%BE%FB%F3%CF%3C%F7%DF%7D%FB%EF%BE%FF%FF%FF"
-	expect resp.http.b64allurl2urllc == "%00%00%00%04%10A%08%20%82%0c0%c3%10A%04%14QE%18a%86%1cq%c7%20%82%08%24%92I%28%a2%8a%2c%b2%cb0%c3%0c4%d3M8%e3%8e%3c%f3%cfA%04%10E%14QI%24%92M4%d3QE%14UUUYe%96%5du%d7a%86%18e%96Yi%a6%9am%b6%dbq%c7%1cu%d7%5dy%e7%9e%7d%f7%df%82%08%20%86%18a%8a%28%a2%8e8%e3%92I%24%96Ye%9ai%a6%9ey%e7%a2%8a%28%a6%9ai%aa%aa%aa%ae%ba%eb%b2%cb%2c%b6%dbm%ba%eb%ae%be%fb%ef%c3%0c0%c7%1cq%cb%2c%b2%cf%3c%f3%d3M4%d7%5du%dbm%b6%df%7d%f7%e3%8e8%e7%9ey%eb%ae%ba%ef%be%fb%f3%cf%3c%f7%df%7d%fb%ef%be%ff%ff%ff"
+	expect resp.http.b64allurl2urllc == resp.http.b64all2urllc
+	expect resp.http.hexlc2hex == "0123456789abcdef"
 	expect resp.http.hexuc2hexuc == "0123456789ABCDEF"
-	expect resp.http.hexlc2hexlc == "0123456789abcdef"
-	expect resp.http.hexuc2hexlc == "0123456789abcdef"
+	expect resp.http.hexlc2hexlc == resp.http.hexlc2hex
+	expect resp.http.hexuc2hex == "0123456789abcdef"
+	expect resp.http.hexuc2hexlc == resp.http.hexuc2hex
 	expect resp.http.hexlc2hexuc == "0123456789ABCDEF"
+	expect resp.http.hexmix2hex == "0123456789abcdef"
 	expect resp.http.hexmix2hexuc == "0123456789ABCDEF"
-	expect resp.http.hexmix2hexlc == "0123456789abcdef"
+	expect resp.http.hexmix2hexlc == resp.http.hexmix2hex
 	expect resp.http.hexparam == "0123456789ABCDEF"
 	expect resp.http.b642b64 == "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
 	expect resp.http.b64url2b64url == "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
@@ -212,70 +289,84 @@ varnish v1 -vcl {
 	    set req.http.urlalldownlc = "%ff%fe%fd%fc%fb%fa%f9%f8%f7%f6%f5%f4%f3%f2%f1%f0%ef%ee%ed%ec%eb%ea%e9%e8%e7%e6%e5%e4%e3%e2%e1%e0%df%de%dd%dc%db%da%d9%d8%d7%d6%d5%d4%d3%d2%d1%d0%cf%ce%cd%cc%cb%ca%c9%c8%c7%c6%c5%c4%c3%c2%c1%c0%bf%be%bd%bc%bb%ba%b9%b8%b7%b6%b5%b4%b3%b2%b1%b0%af%ae%ad%ac%ab%aa%a9%a8%a7%a6%a5%a4%a3%a2%a1%a0%9f%9e%9d%9c%9b%9a%99%98%97%96%95%94%93%92%91%90%8f%8e%8d%8c%8b%8a%89%88%87%86%85%84%83%82%81%80%7f~%7d%7c%7bzyxwvutsrqponmlkjihgfedcba%60_%5e%5d%5c%5bZYXWVUTSRQPONMLKJIHGFEDCBA%40%3f%3e%3d%3c%3b%3a9876543210%2f.-%2c%2b%2a%29%28%27%26%25%24%23%22%21%20%1f%1e%1d%1c%1b%1a%19%18%17%16%15%14%13%12%11%10%0f%0e%0d%0c%0b%0a%09%08%07%06%05%04%03%02%01%00";
 
 	  set resp.http.urluc2id
-	    = blob.transcode(URL, IDENTITY, req.http.urlhobbesuc);
+	    = blob.transcode(URL, IDENTITY, encoded=req.http.urlhobbesuc);
 
 	  set resp.http.urllc2id
-	    = blob.transcode(URL, IDENTITY, req.http.urlhobbeslc);
+	    = blob.transcode(URL, IDENTITY, encoded=req.http.urlhobbeslc);
 
 	  set resp.http.urlalldownuc2b64
-	    = blob.transcode(URL, BASE64, req.http.urlalldownuc);
+	    = blob.transcode(URL, BASE64, encoded=req.http.urlalldownuc);
 
 	  set resp.http.urlalldownuc2b64url
-	    = blob.transcode(URL, BASE64URL, req.http.urlalldownuc);
+	    = blob.transcode(URL, BASE64URL, encoded=req.http.urlalldownuc);
 
 	  set resp.http.urlalldownuc2b64nopad
-	    = blob.transcode(URL, BASE64URLNOPAD, req.http.urlalldownuc);
+	    = blob.transcode(URL, BASE64URLNOPAD,
+	                     encoded=req.http.urlalldownuc);
 
 	  set resp.http.urlalldownlc2b64
-	    = blob.transcode(URL, BASE64, req.http.urlalldownlc);
+	    = blob.transcode(URL, BASE64, encoded=req.http.urlalldownlc);
 
 	  set resp.http.urlalldownlc2b64url
-	    = blob.transcode(URL, BASE64URL, req.http.urlalldownlc);
+	    = blob.transcode(URL, BASE64URL, encoded=req.http.urlalldownlc);
 
 	  set resp.http.urlalldownlc2b64nopad
-	    = blob.transcode(URL, BASE64URLNOPAD, req.http.urlalldownlc);
+	    = blob.transcode(URL, BASE64URLNOPAD,
+	                     encoded=req.http.urlalldownlc);
 
 	  set resp.http.urlallupuc2b64
-	    = blob.transcode(URL, BASE64, req.http.urlallupuc);
+	    = blob.transcode(URL, BASE64, encoded=req.http.urlallupuc);
 
 	  set resp.http.urlallupuc2b64url
-	    = blob.transcode(URL, BASE64URL, req.http.urlallupuc);
+	    = blob.transcode(URL, BASE64URL, encoded=req.http.urlallupuc);
 
 	  set resp.http.urlallupuc2b64nopad
-	    = blob.transcode(URL, BASE64URLNOPAD, req.http.urlallupuc);
+	    = blob.transcode(URL, BASE64URLNOPAD, encoded=req.http.urlallupuc);
 
 	  set resp.http.urlalluplc2b64
-	    = blob.transcode(URL, BASE64, req.http.urlalluplc);
+	    = blob.transcode(URL, BASE64, encoded=req.http.urlalluplc);
 
 	  set resp.http.urlalluplc2b64url
-	    = blob.transcode(URL, BASE64URL, req.http.urlalluplc);
+	    = blob.transcode(URL, BASE64URL, encoded=req.http.urlalluplc);
 
 	  set resp.http.urlalluplc2b64nopad
-	    = blob.transcode(URL, BASE64URLNOPAD, req.http.urlalluplc);
+	    = blob.transcode(URL, BASE64URLNOPAD, encoded=req.http.urlalluplc);
 
-	  set resp.http.urlalldownuc2urluc
-	    = blob.transcode(URL, URLUC, req.http.urlalldownuc);
+	  set resp.http.urlalldownuc2url
+	    = blob.transcode(URL, URL, encoded=req.http.urlalldownuc);
 
 	  set resp.http.urlalldownuc2urllc
-	    = blob.transcode(URL, URLLC, req.http.urlalldownuc);
+	    = blob.transcode(URL, URL, LOWER, req.http.urlalldownuc);
 
-	  set resp.http.urlalldownlc2urluc
-	    = blob.transcode(URL, URLUC, req.http.urlalldownlc);
+	  set resp.http.urlalldownuc2urluc
+	    = blob.transcode(URL, URL, UPPER, req.http.urlalldownuc);
+
+	  set resp.http.urlalldownlc2url
+	    = blob.transcode(URL, URL, encoded=req.http.urlalldownlc);
 
 	  set resp.http.urlalldownlc2urllc
-	    = blob.transcode(URL, URLLC, req.http.urlalldownlc);
+	    = blob.transcode(URL, URL, LOWER, req.http.urlalldownlc);
+
+	  set resp.http.urlalldownlc2urluc
+	    = blob.transcode(URL, URL, UPPER, req.http.urlalldownlc);
+
+	  set resp.http.urlallupuc2url
+	    = blob.transcode(URL, URL, encoded=req.http.urlallupuc);
 
 	  set resp.http.urlallupuc2urluc
-	    = blob.transcode(URL, URLUC, req.http.urlallupuc);
+	    = blob.transcode(URL, URL, UPPER, req.http.urlallupuc);
 
 	  set resp.http.urlallupuc2urllc
-	    = blob.transcode(URL, URLLC, req.http.urlallupuc);
+	    = blob.transcode(URL, URL, LOWER, req.http.urlallupuc);
+
+	  set resp.http.urlalluplc2url
+	    = blob.transcode(URL, URL, encoded=req.http.urlalluplc);
 
 	  set resp.http.urlalluplc2urluc
-	    = blob.transcode(URL, URLUC, req.http.urlalluplc);
+	    = blob.transcode(URL, URL, UPPER, req.http.urlalluplc);
 
 	  set resp.http.urlalluplc2urllc
-	    = blob.transcode(URL, URLLC, req.http.urlalluplc);
+	    = blob.transcode(URL, URL, LOWER, req.http.urlalluplc);
 
 	  }
 }
@@ -297,14 +388,18 @@ client c1 {
 	expect resp.http.urlalluplc2b64 == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="
 	expect resp.http.urlalluplc2b64url == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w=="
 	expect resp.http.urlalluplc2b64nopad == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy8_T19vf4-fr7_P3-_w"
+	expect resp.http.urlalldownuc2url == "%ff%fe%fd%fc%fb%fa%f9%f8%f7%f6%f5%f4%f3%f2%f1%f0%ef%ee%ed%ec%eb%ea%e9%e8%e7%e6%e5%e4%e3%e2%e1%e0%df%de%dd%dc%db%da%d9%d8%d7%d6%d5%d4%d3%d2%d1%d0%cf%ce%cd%cc%cb%ca%c9%c8%c7%c6%c5%c4%c3%c2%c1%c0%bf%be%bd%bc%bb%ba%b9%b8%b7%b6%b5%b4%b3%b2%b1%b0%af%ae%ad%ac%ab%aa%a9%a8%a7%a6%a5%a4%a3%a2%a1%a0%9f%9e%9d%9c%9b%9a%99%98%97%96%95%94%93%92%91%90%8f%8e%8d%8c%8b%8a%89%88%87%86%85%84%83%82%81%80%7f~%7d%7c%7bzyxwvutsrqponmlkjihgfedcba%60_%5e%5d%5c%5bZYXWVUTSRQPONMLKJIHGFEDCBA%40%3f%3e%3d%3c%3b%3a9876543210%2f.-%2c%2b%2a%29%28%27%26%25%24%23%22%21%20%1f%1e%1d%1c%1b%1a%19%18%17%16%15%14%13%12%11%10%0f%0e%0d%0c%0b%0a%09%08%07%06%05%04%03%02%01%00"
 	expect resp.http.urlalldownuc2urluc == "%FF%FE%FD%FC%FB%FA%F9%F8%F7%F6%F5%F4%F3%F2%F1%F0%EF%EE%ED%EC%EB%EA%E9%E8%E7%E6%E5%E4%E3%E2%E1%E0%DF%DE%DD%DC%DB%DA%D9%D8%D7%D6%D5%D4%D3%D2%D1%D0%CF%CE%CD%CC%CB%CA%C9%C8%C7%C6%C5%C4%C3%C2%C1%C0%BF%BE%BD%BC%BB%BA%B9%B8%B7%B6%B5%B4%B3%B2%B1%B0%AF%AE%AD%AC%AB%AA%A9%A8%A7%A6%A5%A4%A3%A2%A1%A0%9F%9E%9D%9C%9B%9A%99%98%97%96%95%94%93%92%91%90%8F%8E%8D%8C%8B%8A%89%88%87%86%85%84%83%82%81%80%7F~%7D%7C%7Bzyxwvutsrqponmlkjihgfedcba%60_%5E%5D%5C%5BZYXWVUTSRQPONMLKJIHGFEDCBA%40%3F%3E%3D%3C%3B%3A9876543210%2F.-%2C%2B%2A%29%28%27%26%25%24%23%22%21%20%1F%1E%1D%1C%1B%1A%19%18%17%16%15%14%13%12%11%10%0F%0E%0D%0C%0B%0A%09%08%07%06%05%04%03%02%01%00"
-	expect resp.http.urlalldownuc2urllc == "%ff%fe%fd%fc%fb%fa%f9%f8%f7%f6%f5%f4%f3%f2%f1%f0%ef%ee%ed%ec%eb%ea%e9%e8%e7%e6%e5%e4%e3%e2%e1%e0%df%de%dd%dc%db%da%d9%d8%d7%d6%d5%d4%d3%d2%d1%d0%cf%ce%cd%cc%cb%ca%c9%c8%c7%c6%c5%c4%c3%c2%c1%c0%bf%be%bd%bc%bb%ba%b9%b8%b7%b6%b5%b4%b3%b2%b1%b0%af%ae%ad%ac%ab%aa%a9%a8%a7%a6%a5%a4%a3%a2%a1%a0%9f%9e%9d%9c%9b%9a%99%98%97%96%95%94%93%92%91%90%8f%8e%8d%8c%8b%8a%89%88%87%86%85%84%83%82%81%80%7f~%7d%7c%7bzyxwvutsrqponmlkjihgfedcba%60_%5e%5d%5c%5bZYXWVUTSRQPONMLKJIHGFEDCBA%40%3f%3e%3d%3c%3b%3a9876543210%2f.-%2c%2b%2a%29%28%27%26%25%24%23%22%21%20%1f%1e%1d%1c%1b%1a%19%18%17%16%15%14%13%12%11%10%0f%0e%0d%0c%0b%0a%09%08%07%06%05%04%03%02%01%00"
+	expect resp.http.urlalldownuc2urllc == resp.http.urlalldownuc2url
+	expect resp.http.urlalldownlc2url == "%ff%fe%fd%fc%fb%fa%f9%f8%f7%f6%f5%f4%f3%f2%f1%f0%ef%ee%ed%ec%eb%ea%e9%e8%e7%e6%e5%e4%e3%e2%e1%e0%df%de%dd%dc%db%da%d9%d8%d7%d6%d5%d4%d3%d2%d1%d0%cf%ce%cd%cc%cb%ca%c9%c8%c7%c6%c5%c4%c3%c2%c1%c0%bf%be%bd%bc%bb%ba%b9%b8%b7%b6%b5%b4%b3%b2%b1%b0%af%ae%ad%ac%ab%aa%a9%a8%a7%a6%a5%a4%a3%a2%a1%a0%9f%9e%9d%9c%9b%9a%99%98%97%96%95%94%93%92%91%90%8f%8e%8d%8c%8b%8a%89%88%87%86%85%84%83%82%81%80%7f~%7d%7c%7bzyxwvutsrqponmlkjihgfedcba%60_%5e%5d%5c%5bZYXWVUTSRQPONMLKJIHGFEDCBA%40%3f%3e%3d%3c%3b%3a9876543210%2f.-%2c%2b%2a%29%28%27%26%25%24%23%22%21%20%1f%1e%1d%1c%1b%1a%19%18%17%16%15%14%13%12%11%10%0f%0e%0d%0c%0b%0a%09%08%07%06%05%04%03%02%01%00"
 	expect resp.http.urlalldownlc2urluc == "%FF%FE%FD%FC%FB%FA%F9%F8%F7%F6%F5%F4%F3%F2%F1%F0%EF%EE%ED%EC%EB%EA%E9%E8%E7%E6%E5%E4%E3%E2%E1%E0%DF%DE%DD%DC%DB%DA%D9%D8%D7%D6%D5%D4%D3%D2%D1%D0%CF%CE%CD%CC%CB%CA%C9%C8%C7%C6%C5%C4%C3%C2%C1%C0%BF%BE%BD%BC%BB%BA%B9%B8%B7%B6%B5%B4%B3%B2%B1%B0%AF%AE%AD%AC%AB%AA%A9%A8%A7%A6%A5%A4%A3%A2%A1%A0%9F%9E%9D%9C%9B%9A%99%98%97%96%95%94%93%92%91%90%8F%8E%8D%8C%8B%8A%89%88%87%86%85%84%83%82%81%80%7F~%7D%7C%7Bzyxwvutsrqponmlkjihgfedcba%60_%5E%5D%5C%5BZYXWVUTSRQPONMLKJIHGFEDCBA%40%3F%3E%3D%3C%3B%3A9876543210%2F.-%2C%2B%2A%29%28%27%26%25%24%23%22%21%20%1F%1E%1D%1C%1B%1A%19%18%17%16%15%14%13%12%11%10%0F%0E%0D%0C%0B%0A%09%08%07%06%05%04%03%02%01%00"
-	expect resp.http.urlalldownlc2urllc == "%ff%fe%fd%fc%fb%fa%f9%f8%f7%f6%f5%f4%f3%f2%f1%f0%ef%ee%ed%ec%eb%ea%e9%e8%e7%e6%e5%e4%e3%e2%e1%e0%df%de%dd%dc%db%da%d9%d8%d7%d6%d5%d4%d3%d2%d1%d0%cf%ce%cd%cc%cb%ca%c9%c8%c7%c6%c5%c4%c3%c2%c1%c0%bf%be%bd%bc%bb%ba%b9%b8%b7%b6%b5%b4%b3%b2%b1%b0%af%ae%ad%ac%ab%aa%a9%a8%a7%a6%a5%a4%a3%a2%a1%a0%9f%9e%9d%9c%9b%9a%99%98%97%96%95%94%93%92%91%90%8f%8e%8d%8c%8b%8a%89%88%87%86%85%84%83%82%81%80%7f~%7d%7c%7bzyxwvutsrqponmlkjihgfedcba%60_%5e%5d%5c%5bZYXWVUTSRQPONMLKJIHGFEDCBA%40%3f%3e%3d%3c%3b%3a9876543210%2f.-%2c%2b%2a%29%28%27%26%25%24%23%22%21%20%1f%1e%1d%1c%1b%1a%19%18%17%16%15%14%13%12%11%10%0f%0e%0d%0c%0b%0a%09%08%07%06%05%04%03%02%01%00"
+	expect resp.http.urlalldownlc2urllc == resp.http.urlalldownlc2url
 	expect resp.http.urlallupuc2urluc == "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF"
 	expect resp.http.urlalluplc2urluc == "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF"
-	expect resp.http.urlallupuc2urllc == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5b%5c%5d%5e_%60abcdefghijklmnopqrstuvwxyz%7b%7c%7d~%7f%80%81%82%83%84%85%86%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe%ff"
-	expect resp.http.urlalluplc2urllc == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5b%5c%5d%5e_%60abcdefghijklmnopqrstuvwxyz%7b%7c%7d~%7f%80%81%82%83%84%85%86%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe%ff"
+	expect resp.http.urlallupuc2url == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5b%5c%5d%5e_%60abcdefghijklmnopqrstuvwxyz%7b%7c%7d~%7f%80%81%82%83%84%85%86%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe%ff"
+	expect resp.http.urlallupuc2urllc == resp.http.urlallupuc2url
+	expect resp.http.urlalluplc2url == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5b%5c%5d%5e_%60abcdefghijklmnopqrstuvwxyz%7b%7c%7d~%7f%80%81%82%83%84%85%86%87%88%89%8a%8b%8c%8d%8e%8f%90%91%92%93%94%95%96%97%98%99%9a%9b%9c%9d%9e%9f%a0%a1%a2%a3%a4%a5%a6%a7%a8%a9%aa%ab%ac%ad%ae%af%b0%b1%b2%b3%b4%b5%b6%b7%b8%b9%ba%bb%bc%bd%be%bf%c0%c1%c2%c3%c4%c5%c6%c7%c8%c9%ca%cb%cc%cd%ce%cf%d0%d1%d2%d3%d4%d5%d6%d7%d8%d9%da%db%dc%dd%de%df%e0%e1%e2%e3%e4%e5%e6%e7%e8%e9%ea%eb%ec%ed%ee%ef%f0%f1%f2%f3%f4%f5%f6%f7%f8%f9%fa%fb%fc%fd%fe%ff"
+	expect resp.http.urlalluplc2urllc == resp.http.urlalluplc2url
 } -run
 
 # Decode failures
@@ -321,53 +416,53 @@ varnish v1 -vcl+backend {
 		set req.http.foo = "AAA=";
 		if (req.url == "/1") {
 			set resp.http.bad
-			    = blob.transcode(HEX, IDENTITY, "0x123456");
+			    = blob.transcode(HEX, IDENTITY, encoded="0x123456");
 		}
 		elsif (req.url == "/2") {
 			set resp.http.bad
 			    = blob.transcode(BASE64, IDENTITY,
-						 "-_-_" + req.http.foo);
+					     encoded="-_-_" + req.http.foo);
 		}
 		elsif (req.url == "/3") {
 			set resp.http.bad
 			    = blob.transcode(BASE64URL, IDENTITY,
-						 "+/+/" + req.http.foo);
+					     encoded="+/+/" + req.http.foo);
 		}
 		elsif (req.url == "/4") {
 			set resp.http.bad
 			    = blob.transcode(BASE64URLNOPAD, IDENTITY,
-						 "TWFu" + req.http.foo);
+					     encoded="TWFu" + req.http.foo);
 		}
 		elsif (req.url == "/5") {
 			set resp.http.bad
 			    = blob.transcode(BASE64, BASE64,
-						 "_-_-" + req.http.foo);
+					     encoded="_-_-" + req.http.foo);
 		}
 		elsif (req.url == "/6") {
 			set resp.http.bad
 			    = blob.transcode(BASE64URL, BASE64URL,
-						 "/+/+" + req.http.foo);
+					     encoded="/+/+" + req.http.foo);
 		}
 		elsif (req.url == "/7") {
 			set resp.http.bad
 			    = blob.transcode(BASE64URLNOPAD, BASE64URLNOPAD,
-						 "Zm9v" + req.http.foo);
+					     encoded="Zm9v" + req.http.foo);
 		}
 		elsif (req.url == "/8") {
 			set resp.http.bad
-			    = blob.transcode(URL, IDENTITY, "%");
+			    = blob.transcode(URL, IDENTITY, encoded="%");
 		}
 		elsif (req.url == "/9") {
 			set resp.http.bad
-			    = blob.transcode(URL, IDENTITY, "%2");
+			    = blob.transcode(URL, IDENTITY, encoded="%2");
 		}
 		elsif (req.url == "/10") {
 			set resp.http.bad
-			    = blob.transcode(URL, IDENTITY, "%q");
+			    = blob.transcode(URL, IDENTITY, encoded="%q");
 		}
 		elsif (req.url == "/11") {
 			set resp.http.bad
-			    = blob.transcode(URL, IDENTITY, "%2q");
+			    = blob.transcode(URL, IDENTITY, encoded="%2q");
 		}
 	}
 }
diff --git a/bin/varnishtest/tests/m00042.vtc b/bin/varnishtest/tests/m00042.vtc
index 37ed285..4a96c0f 100644
--- a/bin/varnishtest/tests/m00042.vtc
+++ b/bin/varnishtest/tests/m00042.vtc
@@ -20,109 +20,187 @@ varnish v1 -vcl {
 {"fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a09f9e9d9c9b9a999897969594939291908f8e8d8c8b8a898887868584838281807f7e7d7c7b7a797877767574737271706f6e6d6c6b6a696867666564636261605f5e5d5c5b5a595857565554535251504f4e4d4c4b4a494847464544434241403f3e3d3c3b3a393837363534333231302f2e2d2c2b2a292827262524232221201f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100"};
 	    set req.http.hexallup =
 {"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"};
-	    set req.http.b64all =
-{"AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZaaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzz0000111122223333444455556666777788889999++++////"};
-	    set req.http.b64allurl =
-{"AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZaaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzz0000111122223333444455556666777788889999----____"};
 
 	  set resp.http.id2id
-	    = blob.transcode_n(5, IDENTITY, IDENTITY, "Hello world");
+	    = blob.transcode_n(5, IDENTITY, IDENTITY, encoded="Hello world");
 
 	  set resp.http.id2b64
-	    = blob.transcode_n(5, IDENTITY, BASE64, req.http.hobbes);
+	    = blob.transcode_n(5, IDENTITY, BASE64, encoded=req.http.hobbes);
 
 	  set resp.http.id2b64nopad
-	    = blob.transcode_n(5, IDENTITY, BASE64URLNOPAD, req.http.hobbes);
+	    = blob.transcode_n(5, IDENTITY, BASE64URLNOPAD,
+	                       encoded=req.http.hobbes);
+
+	  set resp.http.id2hex
+	    = blob.transcode_n(5, IDENTITY, HEX, encoded=req.http.hobbes);
 
 	  set resp.http.id2hexuc
-	    = blob.transcode_n(5, IDENTITY, HEXUC, req.http.hobbes);
+	    = blob.transcode_n(5, IDENTITY, HEX, UPPER, req.http.hobbes);
 
 	  set resp.http.id2hexlc
-	    = blob.transcode_n(5, IDENTITY, HEXLC, req.http.hobbes);
+	    = blob.transcode_n(5, IDENTITY, HEX, LOWER, req.http.hobbes);
+
+	  set resp.http.id2url
+	    = blob.transcode_n(5, IDENTITY, URL, encoded=req.http.foobar);
 
 	  set resp.http.id2urluc
-	    = blob.transcode_n(5, IDENTITY, URLUC, req.http.foobar);
+	    = blob.transcode_n(5, IDENTITY, URL, UPPER, req.http.foobar);
 
 	  set resp.http.id2urllc
-	    = blob.transcode_n(5, IDENTITY, URLLC, req.http.foobar);
+	    = blob.transcode_n(5, IDENTITY, URL, LOWER, req.http.foobar);
 
 	  set resp.http.b642id
-	    = blob.transcode_n(8, BASE64, IDENTITY, req.http.hobbesb64);
+	    = blob.transcode_n(8, BASE64, IDENTITY, encoded=req.http.hobbesb64);
 
 	  set resp.http.hex2id
-	    = blob.transcode_n(12, HEX, IDENTITY, req.http.hexhobbes);
+	    = blob.transcode_n(12, HEX, IDENTITY, encoded=req.http.hexhobbes);
 
 	  set resp.http.hexalldown2b64
-	    = blob.transcode_n(12, HEX, BASE64, req.http.hexalldown);
+	    = blob.transcode_n(12, HEX, BASE64, encoded=req.http.hexalldown);
 
 	  set resp.http.hexalldown2b64url
-	    = blob.transcode_n(12, HEX, BASE64URL, req.http.hexalldown);
+	    = blob.transcode_n(12, HEX, BASE64URL, encoded=req.http.hexalldown);
 
 	  set resp.http.hexalldown2b64nopad
-	    = blob.transcode_n(10, HEX, BASE64URLNOPAD, req.http.hexalldown);
+	    = blob.transcode_n(10, HEX, BASE64URLNOPAD,
+	                       encoded=req.http.hexalldown);
 
 	  set resp.http.hexallup2b64
-	    = blob.transcode_n(12, HEX, BASE64, req.http.hexallup);
+	    = blob.transcode_n(12, HEX, BASE64, encoded=req.http.hexallup);
 
 	  set resp.http.hexallup2b64url
-	    = blob.transcode_n(10, HEX, BASE64URL, req.http.hexallup);
+	    = blob.transcode_n(10, HEX, BASE64URL, encoded=req.http.hexallup);
 
 	  set resp.http.hexallup2b64nopad
-	    = blob.transcode_n(10, HEX, BASE64URLNOPAD, req.http.hexallup);
+	    = blob.transcode_n(10, HEX, BASE64URLNOPAD,
+	                       encoded=req.http.hexallup);
+
+	  set resp.http.hexalldown2url
+	    = blob.transcode_n(12, HEX, URL, encoded=req.http.hexalldown);
 
 	  set resp.http.hexalldown2urluc
-	    = blob.transcode_n(12, HEX, URLUC, req.http.hexalldown);
+	    = blob.transcode_n(12, HEX, URL, UPPER, req.http.hexalldown);
 
 	  set resp.http.hexalldown2urllc
-	    = blob.transcode_n(12, HEX, URLLC, req.http.hexalldown);
+	    = blob.transcode_n(12, HEX, URL, LOWER, req.http.hexalldown);
+
+	  set resp.http.hexallup2url
+	    = blob.transcode_n(12, HEX, URL, encoded=req.http.hexallup);
 
 	  set resp.http.hexallup2urluc
-	    = blob.transcode_n(12, HEX, URLUC, req.http.hexallup);
+	    = blob.transcode_n(12, HEX, URL, UPPER, req.http.hexallup);
 
 	  set resp.http.hexallup2urllc
-	    = blob.transcode_n(12, HEX, URLLC, req.http.hexallup);
+	    = blob.transcode_n(12, HEX, URL, LOWER, req.http.hexallup);
+
+	}
+} -start
+
+client c1 {
+	txreq
+	rxresp
+	expect resp.http.id2id == "Hello"
+	expect resp.http.id2b64 == "TWFuIGk="
+	expect resp.http.id2b64nopad == "TWFuIGk"
+	expect resp.http.id2hex == "4d616e2069"
+	expect resp.http.id2hexuc == "4D616E2069"
+	expect resp.http.id2hexlc == resp.http.id2hex
+	expect resp.http.id2url == "foo%3ab"
+	expect resp.http.id2urluc == "foo%3Ab"
+	expect resp.http.id2urllc == resp.http.id2url
+	expect resp.http.b642id == "Man is"
+	expect resp.http.hex2id == "Man is"
+	expect resp.http.hexalldown2b64 == "//79/Pv6"
+	expect resp.http.hexalldown2b64url == "__79_Pv6"
+	expect resp.http.hexalldown2b64nopad == "__79_Ps"
+	expect resp.http.hexallup2b64 == "AAECAwQF"
+	expect resp.http.hexallup2b64url == "AAECAwQ="
+	expect resp.http.hexallup2b64nopad == "AAECAwQ"
+	expect resp.http.hexalldown2url == "%ff%fe%fd%fc%fb%fa"
+	expect resp.http.hexalldown2urluc == "%FF%FE%FD%FC%FB%FA"
+	expect resp.http.hexalldown2urllc == resp.http.hexalldown2url
+	expect resp.http.hexallup2url == "%00%01%02%03%04%05"
+	expect resp.http.hexallup2urllc == resp.http.hexallup2url
+	expect resp.http.hexallup2urllc == resp.http.hexallup2url
+} -run
+
+varnish v1 -vcl {
+	import blob;
+	import std;
+	backend b { .host = "${bad_ip}"; }
+
+	sub vcl_recv {
+	  return(synth(200));
+	}
+
+	sub vcl_synth {
+	    set req.http.b64all =
+{"AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZaaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzz0000111122223333444455556666777788889999++++////"};
+	    set req.http.b64allurl =
+{"AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZaaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzz0000111122223333444455556666777788889999----____"};
+
+	  set resp.http.b64all2hex
+	    = blob.transcode_n(8, BASE64, HEX, encoded=req.http.b64all);
 
 	  set resp.http.b64all2hexuc
-	    = blob.transcode_n(8, BASE64, HEXUC, req.http.b64all);
+	    = blob.transcode_n(8, BASE64, HEX, UPPER, req.http.b64all);
 
 	  set resp.http.b64all2hexlc
-	    = blob.transcode_n(8, BASE64, HEXLC, req.http.b64all);
+	    = blob.transcode_n(8, BASE64, HEX, LOWER, req.http.b64all);
+
+	  set resp.http.b64allurl2hex
+	    = blob.transcode_n(8, BASE64URL, HEX, encoded=req.http.b64allurl);
 
 	  set resp.http.b64allurl2hexuc
-	    = blob.transcode_n(8, BASE64URL, HEXUC, req.http.b64allurl);
+	    = blob.transcode_n(8, BASE64URL, HEX, UPPER, req.http.b64allurl);
 
 	  set resp.http.b64allurl2hexlc
-	    = blob.transcode_n(8, BASE64URL, HEXLC, req.http.b64allurl);
+	    = blob.transcode_n(8, BASE64URL, HEX, LOWER, req.http.b64allurl);
+
+	  set resp.http.b64all2url
+	    = blob.transcode_n(8, BASE64, URL, encoded=req.http.b64all);
 
 	  set resp.http.b64all2urluc
-	    = blob.transcode_n(8, BASE64, URLUC, req.http.b64all);
+	    = blob.transcode_n(8, BASE64, URL, UPPER, req.http.b64all);
 
 	  set resp.http.b64all2urllc
-	    = blob.transcode_n(8, BASE64, URLLC, req.http.b64all);
+	    = blob.transcode_n(8, BASE64, URL, LOWER, req.http.b64all);
+
+	  set resp.http.b64allurl2url
+	    = blob.transcode_n(8, BASE64URL, URL, encoded=req.http.b64allurl);
 
 	  set resp.http.b64allurl2urluc
-	    = blob.transcode_n(8, BASE64URL, URLUC, req.http.b64allurl);
+	    = blob.transcode_n(8, BASE64URL, URL, UPPER, req.http.b64allurl);
 
 	  set resp.http.b64allurl2urllc
-	    = blob.transcode_n(8, BASE64URL, URLLC, req.http.b64allurl);
+	    = blob.transcode_n(8, BASE64URL, URL, LOWER, req.http.b64allurl);
+
+	  set resp.http.hexuc2hex
+	    = blob.transcode_n(10, HEX, HEX, encoded="0123456789ABCDEF");
 
 	  set resp.http.hexuc2hexuc
-	    = blob.transcode_n(10, HEX, HEXUC, "0123456789ABCDEF");
+	    = blob.transcode_n(10, HEX, HEX, UPPER, "0123456789ABCDEF");
+
+	  set resp.http.hexlc2hex
+	    = blob.transcode_n(10, HEX, HEX, encoded="0123456789abcdef");
 
 	  set resp.http.hexlc2hexlc
-	    = blob.transcode_n(10, HEX, HEXLC, "0123456789abcdef");
+	    = blob.transcode_n(10, HEX, HEX, LOWER, "0123456789abcdef");
 
 	  set resp.http.hexuc2hexlc
-	    = blob.transcode_n(9, HEX, HEXLC, "0123456789ABCDEF");
+	    = blob.transcode_n(9, HEX, HEX, LOWER, "0123456789ABCDEF");
 
 	  set resp.http.hexlc2hexuc
-	    = blob.transcode_n(9, HEX, HEXUC, "0123456789abcdef");
+	    = blob.transcode_n(9, HEX, HEX, UPPER, "0123456789abcdef");
+
+	  set resp.http.hexmix2hex
+	    = blob.transcode_n(13, HEX, HEX, encoded="0123456789abcDEF");
 
 	  set resp.http.hexmix2hexuc
-	    = blob.transcode_n(15, HEX, HEXUC, "0123456789ABCdef");
+	    = blob.transcode_n(15, HEX, HEX, UPPER, "0123456789ABCdef");
 
 	  set resp.http.hexmix2hexlc
-	    = blob.transcode_n(13, HEX, HEXLC, "0123456789abcDEF");
+	    = blob.transcode_n(13, HEX, HEX, LOWER, "0123456789abcDEF");
 
 	  set req.http.hexpart1 = "01234567";
 	  set req.http.hexpart2 = "89abcdef";
@@ -131,62 +209,49 @@ varnish v1 -vcl {
 				   + req.http.unset + "" + req.http.hexpart1
 				   + "" + req.http.unset + "" + req.http.unset
 				   + req.http.hexpart2, decoding=HEX,
-				   encoding=HEXUC, n=10);
+				   encoding=HEX, n=10, case=UPPER);
 
 	  set resp.http.b642b64
-	    = blob.transcode_n(36, BASE64, BASE64,
+	    = blob.transcode_n(36, BASE64, BASE64, encoded=
 				   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
 				   + "ghijklmnopqrstuvwxyz0123456789+/");
 
 	  set resp.http.b64url2b64url =
-	    blob.transcode_n(34, BASE64URL, BASE64URL,
+	    blob.transcode_n(34, BASE64URL, BASE64URL, encoded=
 				 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
 				 + "ghijklmnopqrstuvwxyz0123456789-_");
 
 	  set resp.http.b64urlnopad2b64urlnopad =
-	    blob.transcode_n(34, BASE64URLNOPAD, BASE64URLNOPAD,
+	    blob.transcode_n(34, BASE64URLNOPAD, BASE64URLNOPAD, encoded=
 				 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
 				 + "ghijklmnopqrstuvwxyz0123456789-_");
 
 	}
-} -start
+}
 
 client c1 {
 	txreq
 	rxresp
-	expect resp.http.id2id == "Hello"
-	expect resp.http.id2b64 == "TWFuIGk="
-	expect resp.http.id2b64nopad == "TWFuIGk"
-	expect resp.http.id2hexuc == "4D616E2069"
-	expect resp.http.id2hexlc == "4d616e2069"
-	expect resp.http.id2urluc == "foo%3Ab"
-	expect resp.http.id2urllc == "foo%3ab"
-	expect resp.http.b642id == "Man is"
-	expect resp.http.hex2id == "Man is"
-	expect resp.http.hexalldown2b64 == "//79/Pv6"
-	expect resp.http.hexalldown2b64url == "__79_Pv6"
-	expect resp.http.hexalldown2b64nopad == "__79_Ps"
-	expect resp.http.hexallup2b64 == "AAECAwQF"
-	expect resp.http.hexallup2b64url == "AAECAwQ="
-	expect resp.http.hexallup2b64nopad == "AAECAwQ"
-	expect resp.http.hexalldown2urluc == "%FF%FE%FD%FC%FB%FA"
-	expect resp.http.hexalldown2urllc == "%ff%fe%fd%fc%fb%fa"
-	expect resp.http.hexallup2urluc == "%00%01%02%03%04%05"
-	expect resp.http.hexallup2urllc == "%00%01%02%03%04%05"
-	expect resp.http.b64all2hexuc == "000000041041"
-	expect resp.http.b64all2hexlc == "000000041041"
-	expect resp.http.b64allurl2hexuc == "000000041041"
-	expect resp.http.b64allurl2hexlc == "000000041041"
-	expect resp.http.b64all2urluc == "%00%00%00%04%10A"
-	expect resp.http.b64all2urllc == "%00%00%00%04%10A"
-	expect resp.http.b64allurl2urluc == "%00%00%00%04%10A"
-	expect resp.http.b64allurl2urllc == "%00%00%00%04%10A"
-	expect resp.http.hexuc2hexuc == "0123456789"
-	expect resp.http.hexlc2hexlc == "0123456789"
+	expect resp.http.b64all2hex == "000000041041"
+	expect resp.http.b64all2hexuc == resp.http.b64all2hex
+	expect resp.http.b64all2hexlc == resp.http.b64all2hex
+	expect resp.http.b64allurl2hex == "000000041041"
+	expect resp.http.b64allurl2hexuc == resp.http.b64allurl2hex
+	expect resp.http.b64allurl2hexlc == resp.http.b64allurl2hex
+	expect resp.http.b64all2url == "%00%00%00%04%10A"
+	expect resp.http.b64all2urluc == resp.http.b64all2url
+	expect resp.http.b64all2urllc == resp.http.b64all2url
+	expect resp.http.b64allurl2url == "%00%00%00%04%10A"
+	expect resp.http.b64allurl2urluc == resp.http.b64allurl2url
+	expect resp.http.b64allurl2urllc == resp.http.b64allurl2url
+	expect resp.http.hexuc2hex == "0123456789"
+	expect resp.http.hexlc2hex == resp.http.hexuc2hex
+	expect resp.http.hexlc2hexlc == resp.http.hexuc2hex
 	expect resp.http.hexuc2hexlc == "0012345678"
-	expect resp.http.hexlc2hexuc == "0012345678"
+	expect resp.http.hexlc2hexuc == resp.http.hexuc2hexlc
+	expect resp.http.hexmix2hex == "00123456789abc"
 	expect resp.http.hexmix2hexuc == "00123456789ABCDE"
-	expect resp.http.hexmix2hexlc == "00123456789abc"
+	expect resp.http.hexmix2hexlc == resp.http.hexmix2hex
 	expect resp.http.hexparam == "0123456789"
 	expect resp.http.b642b64 == "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij"
 	expect resp.http.b64url2b64url == "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefeQ=="
@@ -211,74 +276,88 @@ varnish v1 -vcl {
 	    set req.http.urlalldownlc = "%ff%fe%fd%fc%fb%fa%f9%f8%f7%f6%f5%f4%f3%f2%f1%f0%ef%ee%ed%ec%eb%ea%e9%e8%e7%e6%e5%e4%e3%e2%e1%e0%df%de%dd%dc%db%da%d9%d8%d7%d6%d5%d4%d3%d2%d1%d0%cf%ce%cd%cc%cb%ca%c9%c8%c7%c6%c5%c4%c3%c2%c1%c0%bf%be%bd%bc%bb%ba%b9%b8%b7%b6%b5%b4%b3%b2%b1%b0%af%ae%ad%ac%ab%aa%a9%a8%a7%a6%a5%a4%a3%a2%a1%a0%9f%9e%9d%9c%9b%9a%99%98%97%96%95%94%93%92%91%90%8f%8e%8d%8c%8b%8a%89%88%87%86%85%84%83%82%81%80%7f~%7d%7c%7bzyxwvutsrqponmlkjihgfedcba%60_%5e%5d%5c%5bZYXWVUTSRQPONMLKJIHGFEDCBA%40%3f%3e%3d%3c%3b%3a9876543210%2f.-%2c%2b%2a%29%28%27%26%25%24%23%22%21%20%1f%1e%1d%1c%1b%1a%19%18%17%16%15%14%13%12%11%10%0f%0e%0d%0c%0b%0a%09%08%07%06%05%04%03%02%01%00";
 
 	  set resp.http.urluc2id
-	    = blob.transcode_n(27, URL, IDENTITY, req.http.urlhobbesuc);
+	    = blob.transcode_n(27, URL, IDENTITY, encoded=req.http.urlhobbesuc);
 
 	  set resp.http.urllc2id
-	    = blob.transcode_n(63, URL, IDENTITY, req.http.urlhobbeslc);
+	    = blob.transcode_n(63, URL, IDENTITY, encoded=req.http.urlhobbeslc);
 
 	  set resp.http.urlalldownuc2b64
-	    = blob.transcode_n(18, URL, BASE64, req.http.urlalldownuc);
+	    = blob.transcode_n(18, URL, BASE64, encoded=req.http.urlalldownuc);
 
 	  set resp.http.urlalldownuc2b64url
-	    = blob.transcode_n(15, URL, BASE64URL, req.http.urlalldownuc);
+	    = blob.transcode_n(15, URL, BASE64URL,
+	                       encoded=req.http.urlalldownuc);
 
 	  set resp.http.urlalldownuc2b64nopad
 	    = blob.transcode_n(15, URL, BASE64URLNOPAD,
-				   req.http.urlalldownuc);
+			       encoded=req.http.urlalldownuc);
 
 	  set resp.http.urlalldownlc2b64
-	    = blob.transcode_n(18, URL, BASE64, req.http.urlalldownlc);
+	    = blob.transcode_n(18, URL, BASE64, encoded=req.http.urlalldownlc);
 
 	  set resp.http.urlalldownlc2b64url
-	    = blob.transcode_n(15, URL, BASE64URL, req.http.urlalldownlc);
+	    = blob.transcode_n(15, URL, BASE64URL,
+	                       encoded=req.http.urlalldownlc);
 
 	  set resp.http.urlalldownlc2b64nopad
 	    = blob.transcode_n(15, URL, BASE64URLNOPAD,
-				   req.http.urlalldownlc);
+			       encoded=req.http.urlalldownlc);
 
 	  set resp.http.urlallupuc2b64
-	    = blob.transcode_n(36, URL, BASE64, req.http.urlallupuc);
+	    = blob.transcode_n(36, URL, BASE64, encoded=req.http.urlallupuc);
 
 	  set resp.http.urlallupuc2b64url
-	    = blob.transcode_n(33, URL, BASE64URL, req.http.urlallupuc);
+	    = blob.transcode_n(33, URL, BASE64URL, encoded=req.http.urlallupuc);
 
 	  set resp.http.urlallupuc2b64nopad
 	    = blob.transcode_n(33, URL, BASE64URLNOPAD,
-				   req.http.urlallupuc);
+			       encoded=req.http.urlallupuc);
 
 	  set resp.http.urlalluplc2b64
-	    = blob.transcode_n(36, URL, BASE64, req.http.urlalluplc);
+	    = blob.transcode_n(36, URL, BASE64, encoded=req.http.urlalluplc);
 
 	  set resp.http.urlalluplc2b64url
-	    = blob.transcode_n(33, URL, BASE64URL, req.http.urlalluplc);
+	    = blob.transcode_n(33, URL, BASE64URL, encoded=req.http.urlalluplc);
 
 	  set resp.http.urlalluplc2b64nopad
 	    = blob.transcode_n(33, URL, BASE64URLNOPAD,
-				   req.http.urlalluplc);
+			       encoded=req.http.urlalluplc);
+
+	  set resp.http.urlalldownuc2url
+	    = blob.transcode_n(423, URL, URL, encoded=req.http.urlalldownuc);
 
 	  set resp.http.urlalldownuc2urluc
-	    = blob.transcode_n(423, URL, URLUC, req.http.urlalldownuc);
+	    = blob.transcode_n(423, URL, URL, UPPER, req.http.urlalldownuc);
 
 	  set resp.http.urlalldownuc2urllc
-	    = blob.transcode_n(423, URL, URLLC, req.http.urlalldownuc);
+	    = blob.transcode_n(423, URL, URL, LOWER, req.http.urlalldownuc);
+
+	  set resp.http.urlalldownlc2url
+	    = blob.transcode_n(423, URL, URL, encoded=req.http.urlalldownlc);
 
 	  set resp.http.urlalldownlc2urluc
-	    = blob.transcode_n(423, URL, URLUC, req.http.urlalldownlc);
+	    = blob.transcode_n(423, URL, URL, UPPER, req.http.urlalldownlc);
 
 	  set resp.http.urlalldownlc2urllc
-	    = blob.transcode_n(423, URL, URLLC, req.http.urlalldownlc);
+	    = blob.transcode_n(423, URL, URL, LOWER, req.http.urlalldownlc);
+
+	  set resp.http.urlallupuc2url
+	    = blob.transcode_n(197, URL, URL, encoded=req.http.urlallupuc);
 
 	  set resp.http.urlallupuc2urluc
-	    = blob.transcode_n(197, URL, URLUC, req.http.urlallupuc);
+	    = blob.transcode_n(197, URL, URL, UPPER, req.http.urlallupuc);
 
 	  set resp.http.urlallupuc2urllc
-	    = blob.transcode_n(197, URL, URLLC, req.http.urlallupuc);
+	    = blob.transcode_n(197, URL, URL, LOWER, req.http.urlallupuc);
+
+	  set resp.http.urlalluplc2url
+	    = blob.transcode_n(197, URL, URL, encoded=req.http.urlalluplc);
 
 	  set resp.http.urlalluplc2urluc
-	    = blob.transcode_n(197, URL, URLUC, req.http.urlalluplc);
+	    = blob.transcode_n(197, URL, URL, UPPER, req.http.urlalluplc);
 
 	  set resp.http.urlalluplc2urllc
-	    = blob.transcode_n(197, URL, URLLC, req.http.urlalluplc);
+	    = blob.transcode_n(197, URL, URL, LOWER, req.http.urlalluplc);
 
 	  }
 }
@@ -300,14 +379,18 @@ client c1 {
 	expect resp.http.urlalluplc2b64 == "AAECAwQFBgcICQoL"
 	expect resp.http.urlalluplc2b64url == "AAECAwQFBgcICQo="
 	expect resp.http.urlalluplc2b64nopad == "AAECAwQFBgcICQo"
+	expect resp.http.urlalldownuc2url == "%ff%fe%fd%fc%fb%fa%f9%f8%f7%f6%f5%f4%f3%f2%f1%f0%ef%ee%ed%ec%eb%ea%e9%e8%e7%e6%e5%e4%e3%e2%e1%e0%df%de%dd%dc%db%da%d9%d8%d7%d6%d5%d4%d3%d2%d1%d0%cf%ce%cd%cc%cb%ca%c9%c8%c7%c6%c5%c4%c3%c2%c1%c0%bf%be%bd%bc%bb%ba%b9%b8%b7%b6%b5%b4%b3%b2%b1%b0%af%ae%ad%ac%ab%aa%a9%a8%a7%a6%a5%a4%a3%a2%a1%a0%9f%9e%9d%9c%9b%9a%99%98%97%96%95%94%93%92%91%90%8f%8e%8d%8c%8b%8a%89%88%87%86%85%84%83%82%81%80%7f~%7d%7c%7bzyxwvutsrqponmlkjihgfedcba"
 	expect resp.http.urlalldownuc2urluc == "%FF%FE%FD%FC%FB%FA%F9%F8%F7%F6%F5%F4%F3%F2%F1%F0%EF%EE%ED%EC%EB%EA%E9%E8%E7%E6%E5%E4%E3%E2%E1%E0%DF%DE%DD%DC%DB%DA%D9%D8%D7%D6%D5%D4%D3%D2%D1%D0%CF%CE%CD%CC%CB%CA%C9%C8%C7%C6%C5%C4%C3%C2%C1%C0%BF%BE%BD%BC%BB%BA%B9%B8%B7%B6%B5%B4%B3%B2%B1%B0%AF%AE%AD%AC%AB%AA%A9%A8%A7%A6%A5%A4%A3%A2%A1%A0%9F%9E%9D%9C%9B%9A%99%98%97%96%95%94%93%92%91%90%8F%8E%8D%8C%8B%8A%89%88%87%86%85%84%83%82%81%80%7F~%7D%7C%7Bzyxwvutsrqponmlkjihgfedcba"
-	expect resp.http.urlalldownuc2urllc == "%ff%fe%fd%fc%fb%fa%f9%f8%f7%f6%f5%f4%f3%f2%f1%f0%ef%ee%ed%ec%eb%ea%e9%e8%e7%e6%e5%e4%e3%e2%e1%e0%df%de%dd%dc%db%da%d9%d8%d7%d6%d5%d4%d3%d2%d1%d0%cf%ce%cd%cc%cb%ca%c9%c8%c7%c6%c5%c4%c3%c2%c1%c0%bf%be%bd%bc%bb%ba%b9%b8%b7%b6%b5%b4%b3%b2%b1%b0%af%ae%ad%ac%ab%aa%a9%a8%a7%a6%a5%a4%a3%a2%a1%a0%9f%9e%9d%9c%9b%9a%99%98%97%96%95%94%93%92%91%90%8f%8e%8d%8c%8b%8a%89%88%87%86%85%84%83%82%81%80%7f~%7d%7c%7bzyxwvutsrqponmlkjihgfedcba"
+	expect resp.http.urlalldownuc2urllc == resp.http.urlalldownuc2url
+	expect resp.http.urlalldownlc2url == "%ff%fe%fd%fc%fb%fa%f9%f8%f7%f6%f5%f4%f3%f2%f1%f0%ef%ee%ed%ec%eb%ea%e9%e8%e7%e6%e5%e4%e3%e2%e1%e0%df%de%dd%dc%db%da%d9%d8%d7%d6%d5%d4%d3%d2%d1%d0%cf%ce%cd%cc%cb%ca%c9%c8%c7%c6%c5%c4%c3%c2%c1%c0%bf%be%bd%bc%bb%ba%b9%b8%b7%b6%b5%b4%b3%b2%b1%b0%af%ae%ad%ac%ab%aa%a9%a8%a7%a6%a5%a4%a3%a2%a1%a0%9f%9e%9d%9c%9b%9a%99%98%97%96%95%94%93%92%91%90%8f%8e%8d%8c%8b%8a%89%88%87%86%85%84%83%82%81%80%7f~%7d%7c%7bzyxwvutsrqponmlkjihgfedcba"
 	expect resp.http.urlalldownlc2urluc == "%FF%FE%FD%FC%FB%FA%F9%F8%F7%F6%F5%F4%F3%F2%F1%F0%EF%EE%ED%EC%EB%EA%E9%E8%E7%E6%E5%E4%E3%E2%E1%E0%DF%DE%DD%DC%DB%DA%D9%D8%D7%D6%D5%D4%D3%D2%D1%D0%CF%CE%CD%CC%CB%CA%C9%C8%C7%C6%C5%C4%C3%C2%C1%C0%BF%BE%BD%BC%BB%BA%B9%B8%B7%B6%B5%B4%B3%B2%B1%B0%AF%AE%AD%AC%AB%AA%A9%A8%A7%A6%A5%A4%A3%A2%A1%A0%9F%9E%9D%9C%9B%9A%99%98%97%96%95%94%93%92%91%90%8F%8E%8D%8C%8B%8A%89%88%87%86%85%84%83%82%81%80%7F~%7D%7C%7Bzyxwvutsrqponmlkjihgfedcba"
-	expect resp.http.urlalldownlc2urllc == "%ff%fe%fd%fc%fb%fa%f9%f8%f7%f6%f5%f4%f3%f2%f1%f0%ef%ee%ed%ec%eb%ea%e9%e8%e7%e6%e5%e4%e3%e2%e1%e0%df%de%dd%dc%db%da%d9%d8%d7%d6%d5%d4%d3%d2%d1%d0%cf%ce%cd%cc%cb%ca%c9%c8%c7%c6%c5%c4%c3%c2%c1%c0%bf%be%bd%bc%bb%ba%b9%b8%b7%b6%b5%b4%b3%b2%b1%b0%af%ae%ad%ac%ab%aa%a9%a8%a7%a6%a5%a4%a3%a2%a1%a0%9f%9e%9d%9c%9b%9a%99%98%97%96%95%94%93%92%91%90%8f%8e%8d%8c%8b%8a%89%88%87%86%85%84%83%82%81%80%7f~%7d%7c%7bzyxwvutsrqponmlkjihgfedcba"
+	expect resp.http.urlalldownlc2urllc == resp.http.urlalldownlc2url
+	expect resp.http.urlallupuc2url == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+	expect resp.http.urlalluplc2url == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 	expect resp.http.urlallupuc2urluc == "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 	expect resp.http.urlalluplc2urluc == "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-	expect resp.http.urlallupuc2urllc == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-	expect resp.http.urlalluplc2urllc == "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f0123456789%3a%3b%3c%3d%3e%3f%40ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+	expect resp.http.urlallupuc2urllc == resp.http.urlallupuc2url
+	expect resp.http.urlalluplc2urllc == resp.http.urlalluplc2url
 } -run
 
 # Decode failures
@@ -324,55 +407,57 @@ varnish v1 -vcl+backend {
 		set req.http.foo = "AAA=";
 		if (req.url == "/1") {
 			set resp.http.good
-			    = blob.transcode_n(3, URL, IDENTITY, "%2c%q");
+			    = blob.transcode_n(3, URL, IDENTITY,
+			                       encoded="%2c%q");
 		}
 		elsif (req.url == "/2") {
 			set resp.http.good
-			    = blob.transcode_n(3, URL, IDENTITY, "%3a%2q");
+			    = blob.transcode_n(3, URL, IDENTITY,
+			                       encoded="%3a%2q");
 		}
 		elsif (req.url == "/3") {
 			set resp.http.bad
 			    = blob.transcode_n(8, HEX, IDENTITY,
-						   "0x123456");
+					       encoded="0x123456");
 		}
 		elsif (req.url == "/4") {
 			set resp.http.bad
 			    = blob.transcode_n(4, BASE64, IDENTITY,
-						   "-_-_" + req.http.foo);
+					       encoded="-_-_" + req.http.foo);
 		}
 		elsif (req.url == "/5") {
 			set resp.http.bad
 			    = blob.transcode_n(4, BASE64URL, IDENTITY,
-						   "+/+/" + req.http.foo);
+					       encoded="+/+/" + req.http.foo);
 		}
 		elsif (req.url == "/6") {
 			set resp.http.bad
 			    = blob.transcode_n(8, BASE64URLNOPAD, IDENTITY,
-						   "TWFu" + req.http.foo);
+					       encoded="TWFu" + req.http.foo);
 		}
 		elsif (req.url == "/7") {
 			set resp.http.bad
 			    = blob.transcode_n(4, BASE64, BASE64,
-						   "_-_-" + req.http.foo);
+					       encoded="_-_-" + req.http.foo);
 		}
 		elsif (req.url == "/8") {
 			set resp.http.bad
 			    = blob.transcode_n(4, BASE64URL, BASE64URL,
-						   "/+/+" + req.http.foo);
+					       encoded="/+/+" + req.http.foo);
 		}
 		elsif (req.url == "/9") {
 			set resp.http.bad
 			    = blob.transcode_n(8, BASE64URLNOPAD,
-						   BASE64URLNOPAD,
-						   "Zm9v" + req.http.foo);
+					       BASE64URLNOPAD,
+					       encoded="Zm9v" + req.http.foo);
 		}
 		elsif (req.url == "/10") {
 			set resp.http.bad
-			    = blob.transcode_n(1, URL, IDENTITY, "%20");
+			    = blob.transcode_n(1, URL, IDENTITY, encoded="%20");
 		}
 		elsif (req.url == "/11") {
 			set resp.http.bad
-			    = blob.transcode_n(2, URL, IDENTITY, "%20");
+			    = blob.transcode_n(2, URL, IDENTITY, encoded="%20");
 		}
 	}
 }
diff --git a/bin/varnishtest/tests/m00043.vtc b/bin/varnishtest/tests/m00043.vtc
index 7c3408a..7521255 100644
--- a/bin/varnishtest/tests/m00043.vtc
+++ b/bin/varnishtest/tests/m00043.vtc
@@ -33,50 +33,32 @@ varnish v1 -arg "-i serverid" -vcl+backend {
 	}
 
 	sub vcl_synth {
-	  set resp.http.id = blob.encode(IDENTITY, id.get());
-	  set resp.http.idpieces = blob.encode(IDENTITY, idpieces.get());
-	  set resp.http.idparam = blob.encode(IDENTITY, idparam.get());
-	  set resp.http.idempty = blob.encode(IDENTITY, idempty.get());
-	  set resp.http.hexuc = blob.encode(IDENTITY, hexuc.get());
-	  set resp.http.hexlc = blob.encode(IDENTITY, hexlc.get());
-	  set resp.http.hexmix = blob.encode(IDENTITY, hexmix.get());
-	  set resp.http.b64 = blob.encode(IDENTITY, b64.get());
-	  set resp.http.b64nopad = blob.encode(IDENTITY, b64nopad.get());
+	  set resp.http.id = blob.encode(IDENTITY, blob=id.get());
+	  set resp.http.idpieces = blob.encode(IDENTITY, blob=idpieces.get());
+	  set resp.http.idparam = blob.encode(IDENTITY, blob=idparam.get());
+	  set resp.http.idempty = blob.encode(IDENTITY, blob=idempty.get());
+	  set resp.http.hexuc = blob.encode(IDENTITY, blob=hexuc.get());
+	  set resp.http.hexlc = blob.encode(IDENTITY, blob=hexlc.get());
+	  set resp.http.hexmix = blob.encode(IDENTITY, blob=hexmix.get());
+	  set resp.http.b64 = blob.encode(IDENTITY, blob=b64.get());
+	  set resp.http.b64nopad = blob.encode(IDENTITY, blob=b64nopad.get());
 
 	  set resp.http.allhex2b64func = blob.encode(BASE64,
-							 hexall.get());
-	  set resp.http.allb642hexlcfunc = blob.encode(HEXLC,
-							   b64all.get());
+						     blob=hexall.get());
+	  set resp.http.allb642hexlcfunc = blob.encode(HEX,
+						       blob=b64all.get());
 	  set resp.http.allhex2b64meth = hexall.encode(BASE64);
-	  set resp.http.allb642hexlcmeth = b64all.encode(HEXLC);
+	  set resp.http.allb642hexmeth = b64all.encode(HEX);
+	  set resp.http.allb642hexlcmeth = b64all.encode(HEX, LOWER);
 
 	  set resp.http.id2id = id.encode(IDENTITY);
 	  set resp.http.id2b64 = id.encode(BASE64);
 	  set resp.http.id2b64url = id.encode(BASE64URL);
 	  set resp.http.id2b64urlnopad = id.encode(BASE64URLNOPAD);
-	  set resp.http.id2hexuc = id.encode(HEXUC);
-	  set resp.http.id2hexlc = id.encode(HEXLC);
+	  set resp.http.id2hex = id.encode(HEX);
+	  set resp.http.id2hexuc = id.encode(HEX, UPPER);
+	  set resp.http.id2hexlc = id.encode(HEX, LOWER);
 
-	  set resp.http.emptyid = idempty.encode(IDENTITY);
-	  set resp.http.emptyb64 = idempty.encode(BASE64);
-	  set resp.http.emptyb64url = idempty.encode(BASE64URL);
-	  set resp.http.emptyb64urlnopad = idempty.encode(BASE64URLNOPAD);
-	  set resp.http.emptyhexuc = idempty.encode(HEXUC);
-	  set resp.http.emptyhexlc = idempty.encode(HEXLC);
-
-	  set resp.http.hexuc2id = hexuc.encode(IDENTITY);
-	  set resp.http.hexuc2b64 = hexuc.encode(BASE64);
-	  set resp.http.hexuc2b64url = hexuc.encode(BASE64URL);
-	  set resp.http.hexuc2b64nopad = hexuc.encode(BASE64URLNOPAD);
-	  set resp.http.hexuc2hexuc = hexuc.encode(HEXUC);
-	  set resp.http.hexuc2hexlc = hexuc.encode(HEXLC);
-
-	  set resp.http.hexlc2id = hexlc.encode(IDENTITY);
-	  set resp.http.hexlc2b64 = hexlc.encode(BASE64);
-	  set resp.http.hexlc2b64url = hexlc.encode(BASE64URL);
-	  set resp.http.hexlc2b64nopad = hexlc.encode(BASE64URLNOPAD);
-	  set resp.http.hexlc2hexuc = hexlc.encode(HEXUC);
-	  set resp.http.hexlc2hexlc = hexlc.encode(HEXLC);
 	}
 } -start
 
@@ -96,35 +78,88 @@ client c1 {
 	expect resp.http.allhex2b64func == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="
 	expect resp.http.allb642hexlcfunc == "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
 	expect resp.http.allhex2b64meth == "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="
-	expect resp.http.allb642hexlcmeth == "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
+	expect resp.http.allb642hexmeth == "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
+	expect resp.http.allb642hexlcmeth == resp.http.allb642hexmeth
 
 	expect resp.http.id2id == "The quick brown fox jumps over the lazy dog"
 	expect resp.http.id2b64 == "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="
 	expect resp.http.id2b64url == "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="
 	expect resp.http.id2b64urlnopad == "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw"
+	expect resp.http.id2hex == "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67"
 	expect resp.http.id2hexuc == "54686520717569636B2062726F776E20666F78206A756D7073206F76657220746865206C617A7920646F67"
-	expect resp.http.id2hexlc == "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67"
+	expect resp.http.id2hexlc == resp.http.id2hex
+} -run
+
+# run twice to test retrieving cached encodings
+client c1 -run
+
+varnish v1 -vcl+backend {
+	import blob;
 
+	sub vcl_init {
+	  new idempty = blob.blob(IDENTITY, "");
+
+	  new hexuc = blob.blob(HEX, "666F6F206261722062617A2071757578");
+	  new hexlc = blob.blob(HEX, "666f6f206261722062617a2071757578");
+	}
+
+	sub vcl_recv {
+	  return(synth(200));
+	}
+
+	sub vcl_synth {
+	  set resp.http.emptyid = idempty.encode(IDENTITY);
+	  set resp.http.emptyb64 = idempty.encode(BASE64);
+	  set resp.http.emptyb64url = idempty.encode(BASE64URL);
+	  set resp.http.emptyb64urlnopad = idempty.encode(BASE64URLNOPAD);
+	  set resp.http.emptyhex = idempty.encode(HEX);
+	  set resp.http.emptyhexuc = idempty.encode(HEX, UPPER);
+	  set resp.http.emptyhexlc = idempty.encode(HEX, LOWER);
+
+	  set resp.http.hexuc2id = hexuc.encode(IDENTITY);
+	  set resp.http.hexuc2b64 = hexuc.encode(BASE64);
+	  set resp.http.hexuc2b64url = hexuc.encode(BASE64URL);
+	  set resp.http.hexuc2b64nopad = hexuc.encode(BASE64URLNOPAD);
+	  set resp.http.hexuc2hex = hexuc.encode(HEX);
+	  set resp.http.hexuc2hexuc = hexuc.encode(HEX, UPPER);
+	  set resp.http.hexuc2hexlc = hexuc.encode(HEX, LOWER);
+
+	  set resp.http.hexlc2id = hexlc.encode(IDENTITY);
+	  set resp.http.hexlc2b64 = hexlc.encode(BASE64);
+	  set resp.http.hexlc2b64url = hexlc.encode(BASE64URL);
+	  set resp.http.hexlc2b64nopad = hexlc.encode(BASE64URLNOPAD);
+	  set resp.http.hexlc2hex = hexlc.encode(HEX);
+	  set resp.http.hexlc2hexuc = hexlc.encode(HEX, UPPER);
+	  set resp.http.hexlc2hexlc = hexlc.encode(HEX, LOWER);
+	}
+}
+
+client c1 {
+	txreq
+	rxresp
 	expect resp.http.emptyid == ""
 	expect resp.http.emptyb64 == ""
 	expect resp.http.emptyb64url == ""
 	expect resp.http.emptyb64urlnopad == ""
+	expect resp.http.emptyhex == ""
 	expect resp.http.emptyhexuc == ""
-	expect resp.http.emptyhexlc == ""
+	expect resp.http.emptyhexlc == resp.http.emptyhex
 
 	expect resp.http.hexuc2id == "foo bar baz quux"
 	expect resp.http.hexuc2b64 == "Zm9vIGJhciBiYXogcXV1eA=="
 	expect resp.http.hexuc2b64url == "Zm9vIGJhciBiYXogcXV1eA=="
 	expect resp.http.hexuc2b64nopad == "Zm9vIGJhciBiYXogcXV1eA"
+	expect resp.http.hexuc2hex == "666f6f206261722062617a2071757578"
 	expect resp.http.hexuc2hexuc == "666F6F206261722062617A2071757578"
-	expect resp.http.hexuc2hexlc == "666f6f206261722062617a2071757578"
+	expect resp.http.hexuc2hexlc == resp.http.hexuc2hex
 
 	expect resp.http.hexlc2id == "foo bar baz quux"
 	expect resp.http.hexlc2b64 == "Zm9vIGJhciBiYXogcXV1eA=="
 	expect resp.http.hexlc2b64url == "Zm9vIGJhciBiYXogcXV1eA=="
 	expect resp.http.hexlc2b64nopad == "Zm9vIGJhciBiYXogcXV1eA"
+	expect resp.http.hexlc2hex == "666f6f206261722062617a2071757578"
 	expect resp.http.hexlc2hexuc == "666F6F206261722062617A2071757578"
-	expect resp.http.hexlc2hexlc == "666f6f206261722062617a2071757578"
+	expect resp.http.hexlc2hexlc == resp.http.hexlc2hex
 } -run
 
 # run twice to test retrieving cached encodings
@@ -148,28 +183,34 @@ varnish v1 -vcl+backend {
 	  set resp.http.b642b64 = b64.encode(BASE64);
 	  set resp.http.b642b64url = b64.encode(BASE64URL);
 	  set resp.http.b642b64nopad = b64.encode(BASE64URLNOPAD);
-	  set resp.http.b642hexuc = b64.encode(HEXUC);
-	  set resp.http.b642hexlc = b64.encode(HEXLC);
-	  set resp.http.b642urluc = b64.encode(URLUC);
-	  set resp.http.b642urllc = b64.encode(URLLC);
+	  set resp.http.b642hex = b64.encode(HEX);
+	  set resp.http.b642hexuc = b64.encode(HEX, UPPER);
+	  set resp.http.b642hexlc = b64.encode(HEX, LOWER);
+	  set resp.http.b642url = b64.encode(URL);
+	  set resp.http.b642urluc = b64.encode(URL, UPPER);
+	  set resp.http.b642urllc = b64.encode(URL, LOWER);
 
 	  set resp.http.b64url2id = b64url.encode(IDENTITY);
 	  set resp.http.b64url2b64 = b64url.encode(BASE64);
 	  set resp.http.b64url2b64url = b64url.encode(BASE64URL);
 	  set resp.http.b64url2b64nopad = b64url.encode(BASE64URLNOPAD);
-	  set resp.http.b64url2hexuc = b64url.encode(HEXUC);
-	  set resp.http.b64url2hexlc = b64url.encode(HEXLC);
-	  set resp.http.b64url2urluc = b64url.encode(URLUC);
-	  set resp.http.b64url2urllc = b64url.encode(URLLC);
+	  set resp.http.b64url2hex = b64url.encode(HEX);
+	  set resp.http.b64url2hexuc = b64url.encode(HEX, UPPER);
+	  set resp.http.b64url2hexlc = b64url.encode(HEX, LOWER);
+	  set resp.http.b64url2url = b64url.encode(URL);
+	  set resp.http.b64url2urluc = b64url.encode(URL, UPPER);
+	  set resp.http.b64url2urllc = b64url.encode(URL, LOWER);
 
 	  set resp.http.b64nopad2id = b64nopad.encode(IDENTITY);
 	  set resp.http.b64nopad2b64 = b64nopad.encode(BASE64);
 	  set resp.http.b64nopad2b64url = b64nopad.encode(BASE64URL);
 	  set resp.http.b64nopad2b64nopad = b64nopad.encode(BASE64URLNOPAD);
-	  set resp.http.b64nopad2hexuc = b64nopad.encode(HEXUC);
-	  set resp.http.b64nopad2hexlc = b64nopad.encode(HEXLC);
-	  set resp.http.b64nopad2urluc = b64nopad.encode(URLUC);
-	  set resp.http.b64nopad2urllc = b64nopad.encode(URLLC);
+	  set resp.http.b64nopad2hex = b64nopad.encode(HEX);
+	  set resp.http.b64nopad2hexuc = b64nopad.encode(HEX, UPPER);
+	  set resp.http.b64nopad2hexlc = b64nopad.encode(HEX, LOWER);
+	  set resp.http.b64nopad2url = b64nopad.encode(URL);
+	  set resp.http.b64nopad2urluc = b64nopad.encode(URL, UPPER);
+	  set resp.http.b64nopad2urllc = b64nopad.encode(URL, LOWER);
 	}
 }
 
@@ -180,28 +221,34 @@ client c2 {
 	expect resp.http.b642b64 == "L0hlbGxvIHdvcmxkLw=="
 	expect resp.http.b642b64url == "L0hlbGxvIHdvcmxkLw=="
 	expect resp.http.b642b64nopad == "L0hlbGxvIHdvcmxkLw"
+	expect resp.http.b642hex == "2f48656c6c6f20776f726c642f"
 	expect resp.http.b642hexuc == "2F48656C6C6F20776F726C642F"
-	expect resp.http.b642hexlc == "2f48656c6c6f20776f726c642f"
+	expect resp.http.b642hexlc == resp.http.b642hex
+	expect resp.http.b642url == "%2fHello%20world%2f"
 	expect resp.http.b642urluc == "%2FHello%20world%2F"
-	expect resp.http.b642urllc == "%2fHello%20world%2f"
+	expect resp.http.b642urllc == resp.http.b642url
 
 	expect resp.http.b64url2id == "/Hello world/"
 	expect resp.http.b64url2b64 == "L0hlbGxvIHdvcmxkLw=="
 	expect resp.http.b64url2b64url == "L0hlbGxvIHdvcmxkLw=="
 	expect resp.http.b64url2b64nopad == "L0hlbGxvIHdvcmxkLw"
+	expect resp.http.b64url2hex == "2f48656c6c6f20776f726c642f"
 	expect resp.http.b64url2hexuc == "2F48656C6C6F20776F726C642F"
-	expect resp.http.b64url2hexlc == "2f48656c6c6f20776f726c642f"
+	expect resp.http.b64url2hexlc == resp.http.b64url2hex
+	expect resp.http.b64url2url == "%2fHello%20world%2f"
 	expect resp.http.b64url2urluc == "%2FHello%20world%2F"
-	expect resp.http.b64url2urllc == "%2fHello%20world%2f"
+	expect resp.http.b64url2urllc == resp.http.b64url2url
 
 	expect resp.http.b64nopad2id == "/Hello world/"
 	expect resp.http.b64nopad2b64 == "L0hlbGxvIHdvcmxkLw=="
 	expect resp.http.b64nopad2b64url == "L0hlbGxvIHdvcmxkLw=="
 	expect resp.http.b64nopad2b64nopad == "L0hlbGxvIHdvcmxkLw"
+	expect resp.http.b64nopad2hex == "2f48656c6c6f20776f726c642f"
 	expect resp.http.b64nopad2hexuc == "2F48656C6C6F20776F726C642F"
-	expect resp.http.b64nopad2hexlc == "2f48656c6c6f20776f726c642f"
+	expect resp.http.b64nopad2hexlc == resp.http.b64nopad2hex
+	expect resp.http.b64nopad2url == "%2fHello%20world%2f"
 	expect resp.http.b64nopad2urluc == "%2FHello%20world%2F"
-	expect resp.http.b64nopad2urllc == "%2fHello%20world%2f"
+	expect resp.http.b64nopad2urllc == resp.http.b64nopad2url
 } -run
 
 # run twice
@@ -224,46 +271,58 @@ varnish v1 -vcl+backend {
 	}
 
 	sub vcl_synth {
-	  set resp.http.id2urluc = id.encode(URLUC);
-	  set resp.http.id2urllc = id.encode(URLLC);
-	  set resp.http.emptyurluc = idempty.encode(URLUC);
-	  set resp.http.emptyurllc = idempty.encode(URLLC);
-	  set resp.http.url = blob.encode(IDENTITY, url.get());
-	  set resp.http.hexuc2urluc = hexuc.encode(URLUC);
-	  set resp.http.hexuc2urllc = hexuc.encode(URLLC);
-	  set resp.http.hexlc2urluc = hexlc.encode(URLUC);
-	  set resp.http.hexlc2urllc = hexlc.encode(URLLC);
+	  set resp.http.id2url = id.encode(URL);
+	  set resp.http.id2urluc = id.encode(URL, UPPER);
+	  set resp.http.id2urllc = id.encode(URL, LOWER);
+	  set resp.http.emptyurl = idempty.encode(URL);
+	  set resp.http.emptyurluc = idempty.encode(URL, UPPER);
+	  set resp.http.emptyurllc = idempty.encode(URL, LOWER);
+	  set resp.http.url = blob.encode(IDENTITY, blob=url.get());
+	  set resp.http.hexuc2url = hexuc.encode(URL);
+	  set resp.http.hexuc2urluc = hexuc.encode(URL, UPPER);
+	  set resp.http.hexuc2urllc = hexuc.encode(URL, LOWER);
+	  set resp.http.hexlc2url = hexlc.encode(URL);
+	  set resp.http.hexlc2urluc = hexlc.encode(URL, UPPER);
+	  set resp.http.hexlc2urllc = hexlc.encode(URL, LOWER);
 	  set resp.http.url2id = url.encode(IDENTITY);
 	  set resp.http.url2b64 = url.encode(BASE64);
 	  set resp.http.url2b64url = url.encode(BASE64URL);
 	  set resp.http.url2b64nopad = url.encode(BASE64URLNOPAD);
-	  set resp.http.url2hexuc = url.encode(HEXUC);
-	  set resp.http.url2hexlc = url.encode(HEXLC);
-	  set resp.http.url2urluc = url.encode(URLUC);
-	  set resp.http.url2urllc = url.encode(URLLC);
+	  set resp.http.url2hex = url.encode(HEX);
+	  set resp.http.url2hexuc = url.encode(HEX, UPPER);
+	  set resp.http.url2hexlc = url.encode(HEX, LOWER);
+	  set resp.http.url2url = url.encode(URL);
+	  set resp.http.url2urluc = url.encode(URL, UPPER);
+	  set resp.http.url2urllc = url.encode(URL, LOWER);
 	}
 }
 
 client c3 {
 	txreq
 	rxresp
+	expect resp.http.id2url == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
 	expect resp.http.id2urluc == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
-	expect resp.http.id2urllc == "The%20quick%20brown%20fox%20jumps%20over%20the%20lazy%20dog"
+	expect resp.http.id2urllc == resp.http.id2url
+	expect resp.http.emptyurl == ""
 	expect resp.http.emptyurluc == ""
-	expect resp.http.emptyurllc == ""
+	expect resp.http.emptyurllc == resp.http.emptyurl
+	expect resp.http.hexuc2url == "foo%20bar%20baz%20quux"
 	expect resp.http.hexuc2urluc == "foo%20bar%20baz%20quux"
-	expect resp.http.hexuc2urllc == "foo%20bar%20baz%20quux"
+	expect resp.http.hexuc2urllc == resp.http.hexuc2url
+	expect resp.http.hexlc2url == "foo%20bar%20baz%20quux"
 	expect resp.http.hexlc2urluc == "foo%20bar%20baz%20quux"
-	expect resp.http.hexlc2urllc == "foo%20bar%20baz%20quux"
+	expect resp.http.hexlc2urllc == resp.http.hexlc2url
 	expect resp.http.url == "foo:bar:baz:quux"
 	expect resp.http.url2id == "foo:bar:baz:quux"
 	expect resp.http.url2b64 == "Zm9vOmJhcjpiYXo6cXV1eA=="
 	expect resp.http.url2b64url == "Zm9vOmJhcjpiYXo6cXV1eA=="
 	expect resp.http.url2b64nopad == "Zm9vOmJhcjpiYXo6cXV1eA"
+	expect resp.http.url2hex == "666f6f3a6261723a62617a3a71757578"
 	expect resp.http.url2hexuc == "666F6F3A6261723A62617A3A71757578"
-	expect resp.http.url2hexlc == "666f6f3a6261723a62617a3a71757578"
+	expect resp.http.url2hexlc == resp.http.url2hexlc
+	expect resp.http.url2url == "foo%3abar%3abaz%3aquux"
 	expect resp.http.url2urluc == "foo%3Abar%3Abaz%3Aquux"
-	expect resp.http.url2urllc == "foo%3abar%3abaz%3aquux"
+	expect resp.http.url2urllc == resp.http.url2url
 } -run
 
 # run twice
diff --git a/bin/varnishtest/tests/m00044.vtc b/bin/varnishtest/tests/m00044.vtc
index 20b6b51..ba4b757 100644
--- a/bin/varnishtest/tests/m00044.vtc
+++ b/bin/varnishtest/tests/m00044.vtc
@@ -20,7 +20,7 @@ varnish v1 -arg "-p http_max_hdr=128" -vcl+backend {
     sub vcl_deliver {
 	# The .get() method retrieves the BLOB from an object.
 	set resp.http.MyBlob-As-Hex
-	    = blob.encode(blob=myblob.get(), encoding=HEXLC);
+	    = blob.encode(blob=myblob.get(), encoding=HEX);
 
 	# The .encode() method efficiently retrieves an encoding.
 	set resp.http.YourBlob-As-Base64 = yourblob.encode(BASE64);
@@ -29,19 +29,20 @@ varnish v1 -arg "-p http_max_hdr=128" -vcl+backend {
 	# vice versa at runtime.
 	set resp.http.Base64-Encoded
 	    = blob.encode(BASE64,
-			      blob.decode(HEX, req.http.Hex-Encoded));
+			  blob=blob.decode(HEX, req.http.Hex-Encoded));
     }
 
     sub vcl_recv {
 	# transcode() converts from one encoding to another.
 	set req.http.Hex-Encoded
-	    = blob.transcode(decoding=BASE64, encoding=HEXUC, encoded="YmF6");
+	    = blob.transcode(decoding=BASE64, encoding=HEX, case=UPPER,
+	                     encoded="YmF6");
 
 	# transcode() can replace other specific encoding/deconding
 	# vmods - e.g. vmod_urlcode
 	set req.url = blob.transcode(encoded=req.url, decoding=URL);
 	set req.http.url_urlcoded
-	    = blob.transcode(encoded=req.url, encoding=URLLC);
+	    = blob.transcode(encoded=req.url, encoding=URL);
     }
     # get output from recv
     sub vcl_deliver {
@@ -52,7 +53,7 @@ varnish v1 -arg "-p http_max_hdr=128" -vcl+backend {
     # IDENTITY
     sub vcl_deliver {
 	set resp.http.Trunced-Foo1
-	    = blob.encode(IDENTITY, blob.decode(HEX, "666f6f00626172"));
+	    = blob.encode(IDENTITY, blob=blob.decode(HEX, "666f6f00626172"));
 	set resp.http.Trunced-Foo2
 	    = blob.encode(blob=blob.decode(HEX, "666f6f00626172"));
     }
@@ -63,21 +64,21 @@ varnish v1 -arg "-p http_max_hdr=128" -vcl+backend {
 	set resp.http.First = "abc";
 	set resp.http.Second = "def0";
 	set resp.http.Hex-Decoded = blob.encode(
-	    HEXLC,
-	    blob.decode(HEX, resp.http.First + resp.http.Second));
+	    HEX,
+	    blob=blob.decode(HEX, resp.http.First + resp.http.Second));
     }
 
     ############################################################
     # encode - also contains decode examples
     sub vcl_deliver {
 	set resp.http.encode1
-	    = blob.encode(HEXLC, blob.decode(BASE64, "Zm9vYmFyYmF6"));
+	    = blob.encode(HEX, blob=blob.decode(BASE64, "Zm9vYmFyYmF6"));
 
 	# same with named parameters
 	set resp.http.encode2
 	    = blob.encode(blob=blob.decode(encoded="Zm9vYmFyYmF6",
 						   decoding=BASE64),
-			      encoding=HEXLC);
+			      encoding=HEX);
 
 	# convert blob to string
 	set resp.http.encode3
@@ -87,7 +88,8 @@ varnish v1 -arg "-p http_max_hdr=128" -vcl+backend {
     ############################################################
     # transcode
     sub vcl_deliver {
-	set resp.http.Hex2Base64-1 = blob.transcode(HEX, BASE64, "666f6f");
+	set resp.http.Hex2Base64-1
+	    = blob.transcode(HEX, BASE64, encoded="666f6f");
 
 	# same with named parameters
 	set resp.http.Hex2Base64-2
@@ -100,7 +102,7 @@ varnish v1 -arg "-p http_max_hdr=128" -vcl+backend {
 
 	# replacement for urlcode.encode("foo bar")
 	set resp.http.urlencoded
-	    = blob.transcode(encoded="foo bar", encoding=URLLC);
+	    = blob.transcode(encoded="foo bar", encoding=URL);
     }
 
     ############################################################
diff --git a/bin/varnishtest/tests/m00045.vtc b/bin/varnishtest/tests/m00045.vtc
index 654b16a..83697a7 100644
--- a/bin/varnishtest/tests/m00045.vtc
+++ b/bin/varnishtest/tests/m00045.vtc
@@ -183,19 +183,21 @@ varnish v1 -vcl {
 
 	sub vcl_synth {
 		set resp.http.up03
-		    = blob.encode(BASE64, blob.subblob(up07.get(), 4B));
+		    = blob.encode(BASE64, blob=blob.subblob(up07.get(), 4B));
 		set resp.http.down07060504
-		    = blob.encode(BASE64, blob.subblob(down07.get(), 4B));
+		    = blob.encode(BASE64, blob=blob.subblob(down07.get(), 4B));
 		set resp.http.up04050607
-		    = blob.encode(BASE64, blob.subblob(up07.get(), 4B, 4B));
+		    = blob.encode(BASE64,
+		                  blob=blob.subblob(up07.get(), 4B, 4B));
 		set resp.http.down03
-		    = blob.encode(BASE64, blob.subblob(down07.get(), 4B, 4B));
+		    = blob.encode(BASE64,
+		                  blob=blob.subblob(down07.get(), 4B, 4B));
 		set resp.http.up07
-		    = blob.encode(BASE64, blob.subblob(up07.get(), 8B));
+		    = blob.encode(BASE64, blob=blob.subblob(up07.get(), 8B));
 		set resp.http.down07
-		    = blob.encode(BASE64, blob.subblob(down07.get(), 8B));
+		    = blob.encode(BASE64, blob=blob.subblob(down07.get(), 8B));
 		set resp.http.zerobytes
-		    = blob.encode(BASE64, blob.subblob(down07.get(), 0B));
+		    = blob.encode(BASE64, blob=blob.subblob(down07.get(), 0B));
 		set resp.http.zerolen
 		    = blob.length(blob.subblob(down07.get(), 0B));
 	}
@@ -231,16 +233,17 @@ varnish v1 -vcl+backend {
 
 	sub vcl_deliver {
 		if (req.url == "/empty") {
-			set resp.http.empty = blob.encode(BASE64,
+			set resp.http.empty = blob.encode(BASE64, blob=
 			    blob.subblob(empty.get(), 1B));
 		}
 		elsif (req.url == "/toolong") {
 			set resp.http.toolong
-			    = blob.encode(BASE64, blob.subblob(up07.get(), 9B));
+			    = blob.encode(BASE64,
+			                  blob=blob.subblob(up07.get(), 9B));
 		}
 		elsif (req.url == "/badoffset") {
 			set resp.http.badoffset = blob.encode(BASE64,
-			    blob.subblob(up07.get(), 4B, 5B));
+			    blob=blob.subblob(up07.get(), 4B, 5B));
 		}
 	}
 }
diff --git a/bin/varnishtest/tests/v00020.vtc b/bin/varnishtest/tests/v00020.vtc
index ba2dd54..6c8ea69 100644
--- a/bin/varnishtest/tests/v00020.vtc
+++ b/bin/varnishtest/tests/v00020.vtc
@@ -222,7 +222,7 @@ varnish v1 -errvcl {'req.hash': Not available in method 'vcl_recv'.} {
 	import blob;
 	backend b { .host = "127.0.0.1"; }
 	sub vcl_recv {
-		blob.encode(HEXLC, req.hash);
+		blob.encode(HEX, LOWER, req.hash);
 	}
 }
 
@@ -230,7 +230,7 @@ varnish v1 -errvcl {'req.hash': Not available in method 'vcl_hash'.} {
 	import blob;
 	backend b { .host = "127.0.0.1"; }
 	sub vcl_hash {
-		blob.encode(HEXLC, req.hash);
+		blob.encode(HEX, LOWER, req.hash);
 	}
 }
 
diff --git a/lib/libvmod_blob/base64.c b/lib/libvmod_blob/base64.c
index d06e323..a46d88c 100644
--- a/lib/libvmod_blob/base64.c
+++ b/lib/libvmod_blob/base64.c
@@ -80,15 +80,16 @@ decode(char *restrict *restrict dest, char *restrict const buf,
 }
 
 ssize_t
-base64_encode(const enum encoding enc, char *restrict const buf,
-	      const size_t buflen, const char *restrict const inbuf,
-	      const size_t inlength)
+base64_encode(const enum encoding enc, const enum case_e kase,
+	      char *restrict const buf, const size_t buflen,
+	      const char *restrict const inbuf, const size_t inlength)
 {
 	const struct b64_alphabet *alpha = &b64_alphabet[enc];
 	char *p = buf;
 	const uint8_t *in = (const uint8_t *)inbuf;
 	const uint8_t * const end = in + inlength;
 
+	(void) kase;
 	AN(buf);
 	AN(alpha);
 	if (in == NULL || inlength == 0)
diff --git a/lib/libvmod_blob/hex.c b/lib/libvmod_blob/hex.c
index 0195123..b65b07e 100644
--- a/lib/libvmod_blob/hex.c
+++ b/lib/libvmod_blob/hex.c
@@ -75,21 +75,21 @@ hex2byte(const unsigned char hi, const unsigned char lo)
 }
 
 ssize_t
-hex_encode(const enum encoding enc, char *restrict const buf,
-	   const size_t buflen, const char *restrict const in,
-	   const size_t inlen)
+hex_encode(const enum encoding enc, const enum case_e kase,
+	   char *restrict const buf, const size_t buflen,
+	   const char *restrict const in, const size_t inlen)
 {
 	char *p = buf;
 	const char *alphabet = hex_alphabet[0];
 
 	AN(buf);
-	assert(enc == HEXUC || enc == HEXLC);
+	assert(enc == HEX);
 	if (in == NULL || inlen == 0)
 		return 0;
 	if (buflen < hex_encode_l(inlen))
 		return -1;
 
-	if (enc != HEXLC)
+	if (kase == UPPER)
 		alphabet = hex_alphabet[1];
 
 	for (int i = 0; i < inlen; i++) {
diff --git a/lib/libvmod_blob/id.c b/lib/libvmod_blob/id.c
index 3a32061..34bb34b 100644
--- a/lib/libvmod_blob/id.c
+++ b/lib/libvmod_blob/id.c
@@ -50,11 +50,12 @@ id_decode_l(size_t l)
 }
 
 ssize_t
-id_encode(const enum encoding enc, char *restrict const buf,
-	  const size_t buflen, const char *restrict const in,
-	  const size_t inlen)
+id_encode(const enum encoding enc, const enum case_e kase,
+	  char *restrict const buf, const size_t buflen,
+	  const char *restrict const in, const size_t inlen)
 {
 	(void) enc;
+	(void) kase;
 	AN(buf);
 
 	if (buflen < inlen + 1)
diff --git a/lib/libvmod_blob/parse_encoding.c b/lib/libvmod_blob/parse_encoding.c
index b18185f..2f7a538 100644
--- a/lib/libvmod_blob/parse_encoding.c
+++ b/lib/libvmod_blob/parse_encoding.c
@@ -17,9 +17,9 @@ parse_encoding (const char *m) {
 
 	switch (m[0]) {
 	case 'B':	goto _0B;	// BASE64, BASE64URL, BASE64URLNOPAD
-	case 'H':	goto _0H;	// HEX, HEXLC, HEXUC
+	case 'H':	goto _0H;	// HEX
 	case 'I':	goto _0I;	// IDENTITY
-	case 'U':	goto _0U;	// URL, URLLC, URLUC
+	case 'U':	goto _0U;	// URL
 	default:	goto invalid;
 	}
 	 _0B:
@@ -85,39 +85,11 @@ parse_encoding (const char *m) {
 	}
 	goto invalid;
 	 _0H:
-	switch (m[1]) {
-	case 'E':	goto _1HE;	// HEX, HEXLC, HEXUC
-	default:	goto invalid;
-	}
-	 _1HE:
-	switch (m[2]) {
-	case 'X':	goto _2HEX;	// HEX, HEXLC, HEXUC
-	default:	goto invalid;
-	}
-	 _2HEX:
 	//HEX
-	if (term(m[3])) {
+	if ((m[1] == 'E') && (m[2] == 'X') && (term(m[3]))) {
 	    r = HEX;
 	    goto ok;
 	}
-	switch (m[3]) {
-	case 'L':	goto _3HEXL;	// HEXLC
-	case 'U':	goto _3HEXU;	// HEXUC
-	default:	goto invalid;
-	}
-	 _3HEXL:
-	//HEXLC
-	if ((m[4] == 'C') && (term(m[5]))) {
-	    r = HEXLC;
-	    goto ok;
-	}
-	goto invalid;
-	 _3HEXU:
-	//HEXUC
-	if ((m[4] == 'C') && (term(m[5]))) {
-	    r = HEXUC;
-	    goto ok;
-	}
 	goto invalid;
 	 _0I:
 	//IDENTITY
@@ -127,39 +99,11 @@ parse_encoding (const char *m) {
 	}
 	goto invalid;
 	 _0U:
-	switch (m[1]) {
-	case 'R':	goto _1UR;	// URL, URLLC, URLUC
-	default:	goto invalid;
-	}
-	 _1UR:
-	switch (m[2]) {
-	case 'L':	goto _2URL;	// URL, URLLC, URLUC
-	default:	goto invalid;
-	}
-	 _2URL:
 	//URL
-	if (term(m[3])) {
+	if ((m[1] == 'R') && (m[2] == 'L') && (term(m[3]))) {
 	    r = URL;
 	    goto ok;
 	}
-	switch (m[3]) {
-	case 'L':	goto _3URLL;	// URLLC
-	case 'U':	goto _3URLU;	// URLUC
-	default:	goto invalid;
-	}
-	 _3URLL:
-	//URLLC
-	if ((m[4] == 'C') && (term(m[5]))) {
-	    r = URLLC;
-	    goto ok;
-	}
-	goto invalid;
-	 _3URLU:
-	//URLUC
-	if ((m[4] == 'C') && (term(m[5]))) {
-	    r = URLUC;
-	    goto ok;
-	}
 	goto invalid;
   ok:
 	return r;
diff --git a/lib/libvmod_blob/parse_encoding.h b/lib/libvmod_blob/parse_encoding.h
index 6d6068b..472ebf8 100644
--- a/lib/libvmod_blob/parse_encoding.h
+++ b/lib/libvmod_blob/parse_encoding.h
@@ -14,11 +14,7 @@ enum encoding {
 	BASE64URL,
 	BASE64URLNOPAD,
 	HEX,
-	HEXUC,
-	HEXLC,
 	URL,
-	URLLC,
-	URLUC,
 	__MAX_ENCODING
 };
 
diff --git a/lib/libvmod_blob/url.c b/lib/libvmod_blob/url.c
index 7368030..deb7355 100644
--- a/lib/libvmod_blob/url.c
+++ b/lib/libvmod_blob/url.c
@@ -79,20 +79,20 @@ isoutofrange(const uint8_t c)
 }
 
 ssize_t
-url_encode(const enum encoding enc, char *restrict const buf,
-	   const size_t buflen, const char *restrict const in,
-	   const size_t inlen)
+url_encode(const enum encoding enc, const enum case_e kase,
+	   char *restrict const buf, const size_t buflen,
+	   const char *restrict const in, const size_t inlen)
 {
 	char *p = buf;
 	const char * const end = buf + buflen;
 	const char *alphabet = hex_alphabet[0];
 
 	AN(buf);
-	assert(enc == URLUC || enc == URLLC);
+	assert(enc == URL);
 	if (in == NULL || inlen == 0)
 		return 0;
 
-	if (enc != URLLC)
+	if (kase == UPPER)
 		alphabet = hex_alphabet[1];
 
 	for (int i = 0; i < inlen; i++) {
diff --git a/lib/libvmod_blob/vmod.vcc b/lib/libvmod_blob/vmod.vcc
index aa88db4..a5553c6 100644
--- a/lib/libvmod_blob/vmod.vcc
+++ b/lib/libvmod_blob/vmod.vcc
@@ -11,13 +11,13 @@ $Module blob 3 utilities for the VCL blob type
 ::
 
   # binary-to-text encodings
-  STRING blob.encode(ENUM encoding, BLOB blob)
-  BLOB blob.decode(ENUM decoding, STRING_LIST encoded)
-  BLOB blob.decode_n(INT n, ENUM decoding, STRING_LIST encoded)
-  STRING blob.transcode(ENUM decoding, ENUM encoding,
+  STRING blob.encode([ENUM encoding,] [ENUM case,] BLOB blob)
+  BLOB blob.decode([ENUM decoding,] STRING_LIST encoded)
+  BLOB blob.decode_n(INT n, [ENUM decoding,] STRING_LIST encoded)
+  STRING blob.transcode([ENUM decoding,] [ENUM encoding,] [ENUM case,]
 			STRING_LIST encoded)
-  STRING blob.transcode_n(INT n, ENUM decoding, ENUM encoding,
-			  STRING_LIST encoded)
+  STRING blob.transcode_n(INT n, [ENUM decoding,] [ENUM encoding,]
+			  [ENUM case,] STRING_LIST encoded)
 
   # other utilities
   BOOL blob.same(BLOB, BLOB)
@@ -26,9 +26,9 @@ $Module blob 3 utilities for the VCL blob type
   BLOB blob.subblob(BLOB, BYTES length [, BYTES offset])
 
   # blob object
-  new OBJ = blob.blob(ENUM decoding, STRING_LIST encoded)
+  new OBJ = blob.blob([ENUM decoding,] STRING_LIST encoded)
   BLOB <obj>.get()
-  STRING <obj>.encode(ENUM encoding)
+  STRING <obj>.encode([ENUM encoding,] [ENUM case])
 
 DESCRIPTION
 ===========
@@ -47,7 +47,7 @@ Examples::
   sub vcl_deliver {
       # The .get() method retrieves the BLOB from an object.
       set resp.http.MyBlob-As-Hex
-	  = blob.encode(blob=myblob.get(), encoding=HEXLC);
+	  = blob.encode(blob=myblob.get(), encoding=HEX);
 
       # The .encode() method efficiently retrieves an encoding.
       set resp.http.YourBlob-As-Base64 = yourblob.encode(BASE64);
@@ -56,21 +56,22 @@ Examples::
       # vice versa at runtime.
       set resp.http.Base64-Encoded
 	  = blob.encode(BASE64,
-			    blob.decode(HEX, req.http.Hex-Encoded));
+			blob=blob.decode(HEX, req.http.Hex-Encoded));
   }
 
   sub vcl_recv {
       # transcode() converts from one encoding to another.
+      # case=UPPER specifies upper-case hex digits A-F.
       set req.http.Hex-Encoded
-	  = blob.transcode(decoding=BASE64, encoding=HEXUC,
-			     encoded="YmF6");
+	  = blob.transcode(decoding=BASE64, encoding=HEX,
+			   case=UPPER, encoded="YmF6");
 
       # transcode() from URL to IDENTITY effects a URL decode.
       set req.url = blob.transcode(encoded=req.url, decoding=URL);
 
       # transcode() from IDENTITY to URL effects a URL encode.
       set req.http.url_urlcoded
-	  = blob.transcode(encoded=req.url, encoding=URLLC);
+	  = blob.transcode(encoded=req.url, encoding=URL);
   }
 
 ENCODING SCHEMES
@@ -81,7 +82,7 @@ constructor, methods and functions. Decodings convert a (possibly
 concatenated) string into a blob, while encodings convert a blob into
 a string.
 
-ENUM values for a decoding can be one of:
+ENUM values for an encoding scheme can be one of:
 
 * ``IDENTITY``
 * ``BASE64``
@@ -90,20 +91,22 @@ ENUM values for a decoding can be one of:
 * ``HEX``
 * ``URL``
 
-An encoding can be one of:
-
-* ``IDENTITY``
-* ``BASE64``
-* ``BASE64URL``
-* ``BASE64URLNOPAD``
-* ``HEXUC``
-* ``HEXLC``
-* ``URLUC``
-* ``URLLC``
-
 Empty strings are decoded into a "null blob" (of length 0),
 and conversely a null blob is encoded as the empty string.
 
+For encodings with ``HEX`` or ``URL``, you may also specify a ``case``
+ENUM with one of the values ``LOWER`` or ``UPPER`` to produce a string
+with lower- or uppercase hex digits (in ``[a-f]`` or ``[A-F]``),
+respectively. The default value for ``case`` is ``LOWER``.
+
+The ``case`` ENUM is not relevant for decodings; ``HEX`` or ``URL``
+strings to be decoded as BLOBs may have hex digits in either case, or
+in mixed case. The ``case`` ENUM is also ignored for all other
+encodings.  You cannot, for example, produce an uppercase string by
+using the IDENTITY scheme with ``case=UPPER``. To change the case of a
+string, use the ``toupper`` or ``tolower`` functions from
+:ref:`vmod_std(3)`.
+
 IDENTITY
 --------
 
@@ -120,7 +123,7 @@ blob. For example::
   # Decode from the hex encoding for "foo\0bar".
   # The header will be seen as "foo".
   set resp.http.Trunced-Foo1
-    = blob.encode(IDENTITY, blob.decode(HEX, "666f6f00626172"));
+    = blob.encode(IDENTITY, blob=blob.decode(HEX, "666f6f00626172"));
 
 IDENTITY is the default encoding and decoding. So the above can also
 be written as::
@@ -130,6 +133,8 @@ be written as::
   set resp.http.Trunced-Foo2
     = blob.encode(blob=blob.decode(HEX, "666f6f00626172"));
 
+The ``case`` ENUM is ignored for ``IDENTITY`` encodings.
+
 BASE64*
 -------
 
@@ -150,14 +155,16 @@ The ``BASE64URLNOPAD`` encoding uses the same alphabet as
 ``BASE6URL``, but leaves out the padding. Thus the length of an
 encoding with this scheme is not necessarily a mutltiple of four.
 
-HEX*
-----
+The ``case`` ENUM is ignored for for all of the ``BASE64*`` encodings.
+
+HEX
+---
 
-The ``HEX`` decoding converts a hex string, which may contain upper-
-or lowercase characters for hex digits ``A`` through ``f``, into a
-blob. The ``HEXUC`` or ``HEXLC`` encodings convert a blob into a hex
-string with upper- and lowercase digits, respectively. A prefix such
-as ``0x`` is not used for any of these schemes.
+The ``HEX`` encoding scheme converts hex strings into blobs and vice
+versa. For encodings, you may use the ``case`` ENUM to specify upper-
+or lowercase hex digits ``A`` through ``f`` (default ``LOWER``).  A
+prefix such as ``0x`` is not used for an encoding and is illegal for a
+decoding.
 
 If a hex string to be decoded has an odd number of digits, it is
 decoded as if a ``0`` is prepended to it; that is, the first digit is
@@ -168,18 +175,18 @@ byte. For example::
   set resp.http.First = "abc";
   set resp.http.Second = "def0";
   set resp.http.Hex-Decoded
-      = blob.encode(HEXLC, blob.decode(HEX,
-			resp.http.First + resp.http.Second));
+      = blob.encode(HEX, blob=blob.decode(HEX,
+                         resp.http.First + resp.http.Second));
 
-URL*
-----
+URL
+---
 
 The ``URL`` decoding replaces any ``%<2-hex-digits>`` substrings with
 the binary value of the hexadecimal number after the % sign.
 
-The ``URLLC`` and ``URLUC`` encodings implement "percent encoding" as per
-RFC3986, the hexadecimal characters A-F being output in lower- and
-uppercase, respectively.
+The ``URL`` encoding implements "percent encoding" as per RFC3986. The
+``case`` ENUM determines the case of the hex digits, but does not
+affect alphabetic characters that are not percent-encoded.
 
 $Function BLOB decode(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
 			    HEX, URL} decoding="IDENTITY", STRING_LIST encoded)
@@ -187,7 +194,7 @@ $Function BLOB decode(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
 Returns the BLOB derived from the string ``encoded`` according to the
 scheme specified by ``decoding``.
 
-``decoding`` defaults to IDENTITY
+``decoding`` defaults to IDENTITY.
 
 Example::
 
@@ -209,24 +216,25 @@ the encoded string. If ``n`` is greater than the length of the string,
 then return the same result as ``decode()``.
 
 $Function STRING encode(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
-			      HEXUC, HEXLC, URLUC, URLLC} encoding="IDENTITY",
-			      BLOB blob)
+			      HEX, URL} encoding="IDENTITY",
+			ENUM {LOWER, UPPER} case="LOWER", BLOB blob)
 
 Returns a string representation of the BLOB ``blob`` as specifed by
-``encoding``.
+``encoding``. ``case`` determines the case of hex digits for the
+``HEX`` and ``URL`` encodings, and is ignored for the other encodings.
 
-``encoding`` defaults to IDENTITY
+``encoding`` defaults to IDENTITY, and ``case`` defaults to LOWER.
 
 Example::
 
 	set resp.http.encode1
-	    = blob.encode(HEXLC, blob.decode(BASE64, "Zm9vYmFyYmF6"));
+	    = blob.encode(HEX, blob=blob.decode(BASE64, "Zm9vYmFyYmF6"));
 
 	# same with named parameters
 	set resp.http.encode2
 	    = blob.encode(blob=blob.decode(encoded="Zm9vYmFyYmF6",
 						   decoding=BASE64),
-			      encoding=HEXLC);
+			      encoding=HEX);
 
 	# convert blob to string
 	set resp.http.encode3
@@ -235,28 +243,32 @@ Example::
 $Function STRING transcode(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
 				 HEX, URL} decoding="IDENTITY",
 			   ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
-				 HEXUC, HEXLC, URLUC, URLLC} encoding="IDENTITY",
+				 HEX, URL} encoding="IDENTITY",
+			   ENUM {LOWER, UPPER} case="LOWER",
 			   STRING_LIST encoded)
 
 Translates from one encoding to another, by first decoding the string
 ``encoded`` according to the scheme ``decoding``, and then returning
 the encoding of the resulting blob according to the scheme
-``encoding``.
+``encoding``. ``case`` determines the case of hex digits for the
+``HEX`` and ``URL`` encodings, and is ignored for other encodings.
 
-``decoding`` and ``encoding`` default to IDENTITY
+``decoding`` and ``encoding`` default to IDENTITY, and ``case``
+defaults to LOWER.
 
 Example::
 
-	set resp.http.Hex2Base64-1 = blob.transcode(HEX, BASE64, "666f6f");
+       set resp.http.Hex2Base64-1
+            = blob.transcode(HEX, BASE64, encoded="666f6f");
 
 	# same with named parameters
 	set resp.http.Hex2Base64-2
-	    = blob.transcode(encoded="666f6f",
+	   = blob.transcode(encoded="666f6f",
 				 encoding=BASE64, decoding=HEX);
 
 	# URL decode -- recall that IDENTITY is the default encoding.
 	set resp.http.urldecoded
-	    = blob.transcode(encoded="foo%20bar", decoding=URLLC);
+	   = blob.transcode(encoded="foo%20bar", decoding=URL);
 
 	# URL encode
 	set resp.http.urlencoded
@@ -266,7 +278,8 @@ $Function STRING transcode_n(INT n,
 			     ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
 				   HEX, URL} decoding="IDENTITY",
 			     ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD,
-				   HEXUC, HEXLC, URLUC, URLLC} encoding="IDENTITY",
+				   HEX, URL} encoding="IDENTITY",
+			     ENUM {LOWER, UPPER} case="LOWER",
 			     STRING_LIST encoded)
 
 Same as ``transcode()``, but only from the first ``n`` characters of
@@ -336,11 +349,14 @@ Example::
 	set resp.http.The-Stringblob =
 	    blob.encode(blob=stringblob.get());
 
-$Method STRING .encode(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, HEXUC,
-			     HEXLC, URLUC, URLLC} encoding="IDENTITY")
+$Method STRING .encode(ENUM {IDENTITY, BASE64, BASE64URL, BASE64URLNOPAD, HEX,
+			     URL} encoding="IDENTITY",
+		       ENUM {LOWER, UPPER} case="LOWER")
 
 Returns an encoding of BLOB created by the constructor, according to
-the scheme ``encoding``.
+the scheme ``encoding``. ``case`` determines the case of hex digits
+for the ``HEX`` and ``URL`` encodings, and is ignored for other
+encodings.
 
 Example::
 
@@ -350,11 +366,11 @@ Example::
 	# blob as base64
 	set resp.http.The-Blob-b64 = theblob1.encode(BASE64);
 
-For any ``blob`` object and encoding ``ENC``, encodings via the ``.encode()``
-method and the ``encode()`` function are equal::
+For any ``blob`` object, encoding ``ENC`` and case ``CASE``, encodings
+via the ``.encode()`` method and the ``encode()`` function are equal::
 
   # Always true:
-  blob.encode(ENC, blob.get()) == blob.encode(ENC)
+  blob.encode(ENC, CASE, blob.get()) == blob.encode(ENC, CASE)
 
 But the object method is more efficient -- the encoding is computed
 once and cached (with allocation in heap memory), and the cached
@@ -416,3 +432,4 @@ SEE ALSO
 
 * :ref:`varnishd(1)`
 * :ref:`vcl(7)`
+* :ref:`vmod_std(3)`
diff --git a/lib/libvmod_blob/vmod_blob.c b/lib/libvmod_blob/vmod_blob.c
index 6bb37ed..850f975 100644
--- a/lib/libvmod_blob/vmod_blob.c
+++ b/lib/libvmod_blob/vmod_blob.c
@@ -42,7 +42,7 @@ struct vmod_blob_blob {
 	unsigned magic;
 #define VMOD_BLOB_MAGIC 0xfade4fa9
 	struct vmod_priv blob;
-	char *encoding[__MAX_ENCODING];
+	char *encoding[__MAX_ENCODING][2];
 	pthread_mutex_t lock;
 };
 
@@ -51,18 +51,6 @@ struct vmod_blob_blob {
 		.decode		= base64_decode,   \
 		.encode		= base64_encode
 
-#define HEX_FUNCS				\
-		.decode_l	= hex_decode_l, \
-		.decode		= hex_decode,	\
-		.encode_l	= hex_encode_l, \
-		.encode		= hex_encode
-
-#define URL_FUNCS				\
-		.decode_l	= url_decode_l, \
-		.decode		= url_decode,	\
-		.encode_l	= url_encode_l, \
-		.encode		= url_encode
-
 static const struct vmod_blob_fptr {
 	len_f		*const decode_l;
 	decode_f	*const decode;
@@ -95,28 +83,20 @@ static const struct vmod_blob_fptr {
 		.encode_l	= base64nopad_encode_l
 	},
 	[HEX] = {
-		HEX_FUNCS
-	},
-	[HEXUC] = {
-		HEX_FUNCS
-	},
-	[HEXLC] = {
-		HEX_FUNCS
+		.decode_l	= hex_decode_l,
+		.decode		= hex_decode,
+		.encode_l	= hex_encode_l,
+		.encode		= hex_encode
 	},
 	[URL] = {
-		URL_FUNCS
-	},
-	[URLUC] = {
-		URL_FUNCS
+		.decode_l	= url_decode_l,
+		.decode		= url_decode,
+		.encode_l	= url_encode_l,
+		.encode		= url_encode
 	},
-	[URLLC] = {
-		URL_FUNCS
-	}
 };
 
 #undef B64_FUNCS
-#undef HEX_FUNCS
-#undef URL_FUNCS
 
 #define ERR(ctx, msg) \
 	VRT_fail((ctx), "vmod blob error: " msg)
@@ -175,6 +155,21 @@ err_decode(VRT_CTX, const char *enc)
 	}
 }
 
+static inline enum case_e
+parse_case(VCL_ENUM case_s)
+{
+	switch(*case_s) {
+	case 'L':
+		AZ(strcmp(case_s + 1, "OWER"));
+		return LOWER;
+	case 'U':
+		AZ(strcmp(case_s + 1, "PPER"));
+		return UPPER;
+	default:
+		WRONG("illegal case enum");
+	}
+}
+
 /* Objects */
 
 VCL_VOID __match_proto__(td_blob_blob__init)
@@ -245,10 +240,12 @@ vmod_blob_get(VRT_CTX, struct vmod_blob_blob *b)
 }
 
 VCL_STRING __match_proto__(td_blob_blob_encode)
-vmod_blob_encode(VRT_CTX, struct vmod_blob_blob *b, VCL_ENUM encs)
+vmod_blob_encode(VRT_CTX, struct vmod_blob_blob *b, VCL_ENUM encs,
+		 VCL_ENUM case_s)
 {
 	enum encoding enc = parse_encoding(encs);
 	AENC(enc);
+	enum case_e kase = parse_case(case_s);
 
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
 	CHECK_OBJ_NOTNULL(b, VMOD_BLOB_MAGIC);
@@ -256,29 +253,29 @@ vmod_blob_encode(VRT_CTX, struct vmod_blob_blob *b, VCL_ENUM encs)
 	if (b->blob.len == 0)
 		return "";
 
-	if (b->encoding[enc] == NULL) {
+	if (b->encoding[enc][kase] == NULL) {
 		AZ(pthread_mutex_lock(&b->lock));
-		if (b->encoding[enc] == NULL) {
+		if (b->encoding[enc][kase] == NULL) {
 			ssize_t len = func[enc].encode_l(b->blob.len);
 
 			assert(len >= 0);
 			if (len == 0)
-				b->encoding[enc] = empty;
+				b->encoding[enc][kase] = empty;
 			else {
-				b->encoding[enc] = malloc(len);
-				if (b->encoding[enc] == NULL)
+				b->encoding[enc][kase] = malloc(len);
+				if (b->encoding[enc][kase] == NULL)
 					ERRNOMEM(ctx, "cannot encode");
 				else {
-					char *s = b->encoding[enc];
+					char *s = b->encoding[enc][kase];
 					len =
 						func[enc].encode(
-							enc, s, len,
+							enc, kase, s, len,
 							b->blob.priv,
 							b->blob.len);
 					assert(len >= 0);
 					if (len == 0) {
 						free(s);
-						b->encoding[enc] = empty;
+						b->encoding[enc][kase] = empty;
 					}
 					else
 						s[len] = '\0';
@@ -287,7 +284,7 @@ vmod_blob_encode(VRT_CTX, struct vmod_blob_blob *b, VCL_ENUM encs)
 		}
 		AZ(pthread_mutex_unlock(&b->lock));
 	}
-	return b->encoding[enc];
+	return b->encoding[enc][kase];
 }
 
 VCL_VOID __match_proto__(td_blob_blob__fini)
@@ -306,9 +303,12 @@ vmod_blob__fini(struct vmod_blob_blob **blobp)
 		b->blob.priv = NULL;
 	}
 	for (int i = 0; i < __MAX_ENCODING; i++)
-		if (b->encoding[i] != NULL && b->encoding[i] != empty) {
-			free(b->encoding[i]);
-			b->encoding[i] = NULL;
+		for (int j = 0; j < 2; j++) {
+			char *s = b->encoding[i][j];
+			if (s != NULL && s != empty) {
+				free(s);
+				b->encoding[i][j] = NULL;
+			}
 		}
 	AZ(pthread_mutex_destroy(&b->lock));
 	FREE_OBJ(b);
@@ -413,7 +413,7 @@ vmod_decode_n(VRT_CTX, VCL_INT n, VCL_ENUM decs, const char *p, ...)
 }
 
 static VCL_STRING
-encode(VRT_CTX, enum encoding enc, VCL_BLOB b)
+encode(VRT_CTX, enum encoding enc, enum case_e kase, VCL_BLOB b)
 {
 	struct wb_s wb;
 	ssize_t len;
@@ -430,7 +430,7 @@ encode(VRT_CTX, enum encoding enc, VCL_BLOB b)
 		return NULL;
 	}
 
-	len = func[enc].encode(enc,
+	len = func[enc].encode(enc, kase,
 			       wb_buf(&wb), wb_space(&wb), b->priv, b->len);
 
 	if (len == -1) {
@@ -447,18 +447,26 @@ encode(VRT_CTX, enum encoding enc, VCL_BLOB b)
 }
 
 VCL_STRING __match_proto__(td_blob_encode)
-vmod_encode(VRT_CTX, VCL_ENUM encs, VCL_BLOB b)
+vmod_encode(VRT_CTX, VCL_ENUM encs, VCL_ENUM case_s, VCL_BLOB b)
 {
 	enum encoding enc = parse_encoding(encs);
-	return encode(ctx, enc, b);
+	enum case_e kase = parse_case(case_s);
+	return encode(ctx, enc, kase, b);
+}
+
+static inline int
+encodes_hex(enum encoding enc)
+{
+	return (enc == HEX || enc == URL);
 }
 
 static VCL_STRING
-transcode(VRT_CTX, VCL_INT n, VCL_ENUM decs, VCL_ENUM encs,
+transcode(VRT_CTX, VCL_INT n, VCL_ENUM decs, VCL_ENUM encs, VCL_ENUM case_s,
 	  const char *restrict const p, va_list ap)
 {
 	enum encoding dec = parse_encoding(decs);
 	enum encoding enc = parse_encoding(encs);
+	enum case_e kase = parse_case(case_s);
 	va_list aq;
 	struct vmod_priv b;
 	VCL_STRING r;
@@ -497,8 +505,11 @@ transcode(VRT_CTX, VCL_INT n, VCL_ENUM decs, VCL_ENUM encs,
 	 * If the encoding and decoding are the same, and the decoding was
 	 * legal, just return the string, if there was only one in the
 	 * STRING_LIST, or else the concatenated string.
+	 * For encodings with hex digits, we cannot assume the same result.
+	 * since the call may specify upper- or lower-case that differs
+	 * from the encoded string.
 	 */
-	if (n == -1 && enc == dec) {
+	if (n == -1 && enc == dec && !encodes_hex(enc)) {
 		const char *q, *pp = p;
 		va_copy(aq, ap);
 		q = find_nonempty_va(&pp, ap);
@@ -514,19 +525,19 @@ transcode(VRT_CTX, VCL_INT n, VCL_ENUM decs, VCL_ENUM encs,
 		return r;
 	}
 
-	r = encode(ctx, enc, &b);
+	r = encode(ctx, enc, kase, &b);
 	return (r);
 }
 
 VCL_STRING __match_proto__(td_blob_transcode)
-vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs,
+vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs, VCL_ENUM case_s,
 	       const char *p, ...)
 {
 	va_list ap;
 	VCL_STRING r;
 
 	va_start(ap, p);
-	r = transcode(ctx, -1, decs, encs, p, ap);
+	r = transcode(ctx, -1, decs, encs, case_s, p, ap);
 	va_end(ap);
 
 	return (r);
@@ -534,13 +545,13 @@ vmod_transcode(VRT_CTX, VCL_ENUM decs, VCL_ENUM encs,
 
 VCL_STRING __match_proto__(td_blob_transcode_n)
 vmod_transcode_n(VRT_CTX, VCL_INT n, VCL_ENUM decs, VCL_ENUM encs,
-		 const char *p, ...)
+		 VCL_ENUM case_s, const char *p, ...)
 {
 	va_list ap;
 	VCL_STRING r;
 
 	va_start(ap, p);
-	r = transcode(ctx, n, decs, encs, p, ap);
+	r = transcode(ctx, n, decs, encs, case_s, p, ap);
 	va_end(ap);
 
 	return (r);
diff --git a/lib/libvmod_blob/vmod_blob.h b/lib/libvmod_blob/vmod_blob.h
index 3953035..9cc1d45 100644
--- a/lib/libvmod_blob/vmod_blob.h
+++ b/lib/libvmod_blob/vmod_blob.h
@@ -34,6 +34,11 @@
 
 #define AENC(enc) assert((enc) > _INVALID && (enc) < __MAX_ENCODING)
 
+enum case_e {
+	LOWER,
+	UPPER,
+};
+
 /*
  * Length estimate interface
  */
@@ -46,6 +51,7 @@ size_t  len_f(size_t);
  * encoding.
  *
  * enc: encoding enum (from parse_encoding.h)
+ * kase: case enum (for encodings with hex digits)
  * buf: destination of the encoded string
  * buflen: maximum length available at buf
  * in: source of data to be encoded
@@ -65,9 +71,9 @@ size_t  len_f(size_t);
  *            include any terminating null byte)
  */
 typedef
-ssize_t encode_f(const enum encoding enc, char *restrict const buf,
-		 const size_t buflen, const char *restrict const in,
-		 const size_t inlen);
+ssize_t encode_f(const enum encoding enc, const enum case_e kase,
+		 char *restrict const buf, const size_t buflen,
+		 const char *restrict const in, const size_t inlen);
 
 /*
  * General interface for a decoder: decode the concatenation of strings


More information about the varnish-commit mailing list