switch from OLPC canonical JSON to a JSON subset

fixes #92
diff --git a/src/interchange/cjson.rs b/src/interchange/cjson.rs
index f0baee8..397bfc5 100644
--- a/src/interchange/cjson.rs
+++ b/src/interchange/cjson.rs
@@ -1,7 +1,6 @@
 use itoa;
 use json;
 use std::collections::BTreeMap;
-use std::io;
 
 pub fn canonicalize(jsn: &json::Value) -> Result<Vec<u8>, String> {
     let converted = convert(jsn)?;
@@ -36,7 +35,11 @@
                 })
             }
             &Value::String(ref s) => {
-                escape_str(&mut buf, &s).map_err(|err| format!("Write error: {}", err))
+                // this mess is abusing serde_json to get json escaping
+                let s = json::Value::String(s.clone());
+                let s = json::to_string(&s)
+                    .map_err(|e| format!("{:?}", e))?;
+                Ok(buf.extend(s.as_bytes()))
             }
             &Value::Array(ref arr) => {
                 buf.push(b'[');
@@ -58,9 +61,13 @@
                         buf.push(b',');
                     }
                     first = false;
-                    escape_str(&mut buf, &k).map_err(|err| {
-                        format!("Write error: {}", err)
-                    })?;
+                    
+                    // this mess is abusing serde_json to get json escaping
+                    let k = json::Value::String(k.clone());
+                    let k = json::to_string(&k)
+                        .map_err(|e| format!("{:?}", e))?;
+                    buf.extend(k.as_bytes());
+
                     buf.push(b':');
                     v.write(&mut buf)?;
                 }
@@ -104,73 +111,10 @@
     }
 }
 
-/// Serializes and escapes a `&str` into a JSON string.
-fn escape_str<W>(wr: &mut W, value: &str) -> Result<(), io::Error>
-where
-    W: io::Write,
-{
-    let bytes = value.as_bytes();
-
-    wr.write_all(b"\"")?;
-
-    let mut start = 0;
-
-    for (i, &byte) in bytes.iter().enumerate() {
-        let escape = ESCAPE[byte as usize];
-        if escape == 0 {
-            continue;
-        }
-
-        if start < i {
-            wr.write_all(&bytes[start..i])?;
-        }
-
-        wr.write_all(&[b'\\', escape])?;
-
-        start = i + 1;
-    }
-
-    if start != bytes.len() {
-        wr.write_all(&bytes[start..])?;
-    }
-
-    wr.write_all(b"\"")?;
-    Ok(())
-}
-
-const QU: u8 = b'"'; // \x22
-const BS: u8 = b'\\'; // \x5C
-
-// Lookup table of escape sequences. A value of b'x' at index i means that byte
-// i is escaped as "\x" in JSON. A value of 0 means that byte i is not escaped.
-#[cfg_attr(rustfmt, rustfmt_skip)]
-static ESCAPE: [u8; 256] = [
-    //  1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 0
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 1
-    0,  0, QU,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 2
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 3
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 4
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, BS,  0,  0,  0, // 5
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 6
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 7
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 8
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // 9
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // A
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // B
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // C
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // D
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // E
-    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, // F
-];
-
 #[cfg(test)]
 mod test {
     use super::*;
 
-    use std::fs::File;
-    use std::io::Read;
-
     #[test]
     fn write_str() {
         let jsn = Value::String(String::from("wat"));
@@ -204,25 +148,4 @@
         jsn.write(&mut out).expect("write failed");
         assert_eq!(&out, b"{\"lol\":[\"haha\",\"omg so tired\"]}");
     }
-
-    #[test]
-    fn root_json() {
-        let mut file = File::open("./tests/cjson/root.json").expect("couldn't open root.json");
-        let mut buf = String::new();
-        file.read_to_string(&mut buf).expect(
-            "couldn't read root.json",
-        );
-
-        let mut file = File::open("./tests/cjson/root.cjson").expect("couldn't open root.cjson");
-        let mut cjsn = String::new();
-        file.read_to_string(&mut cjsn).expect(
-            "couldn't read root.cjson",
-        );
-
-        let ref jsn = json::from_str(&buf).expect("not json");
-        let out = canonicalize(jsn).expect("couldn't canonicalize");
-        let out = ::std::str::from_utf8(&out).expect("not utf-8");
-
-        assert_eq!(out, cjsn);
-    }
 }
diff --git a/tests/cjson/root.cjson b/tests/cjson/root.cjson
deleted file mode 100644
index e132582..0000000
--- a/tests/cjson/root.cjson
+++ /dev/null
@@ -1,33 +0,0 @@
-{"signatures":[{"keyid":"ed3c845525d34937bf0584989a76fa300c0a6072de714b11b8dca535e10b9088","method":"rsassa-pss-sha256","sig":"49bdc0586c83afad062c608a70a5cfd6dd32bf47eb7830960322723615f723fbf43c7d80dab455b08114624d89de740b2547bece8fda01a8acaecf651fcbe98f291971de695fb2f00889bd1ec076e9d431c4c004791dc5e223f023301eca865c0ede005952dfa4fc7b1a591f8875445872d6162039d5e59418998e0c99a15ad28689b82b72099926354ca253cffafe7a3f7ececb9ecddda35cecb05ea9ca184c7ea942ea8a1a49b7445803dd3a14d74697d220f59cef5d56bc9b640d8aca2328f0d6ea4aa25ba79164ecdf31904a176b6100188970d37860c2612cf4571613fdbaa29080be50cae2966dd46a677acaf1dd500d7a86d025877aab0fdaa72f1856"}],"signed":{"_type":"Root","consistent_snapshot":false,"expires":"2038-01-19T03:14:06Z","keys":{"0bde74244f238cd6d4e3839d35a5b248d6cde5759b760ebdbee45a386109a41a":{"keytype":"rsa","keyval":{"public":"-----BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8QLzN27B3+DKhWR8nJZO
-ScZ6XS2mubhqcr3giT+WJejjVH4zIlaeC5tosaY96VKI5vRd4aFgQwq2XEx+YTJM
-dAaUGOUSvPYa+iv+O0ilPeYyXazoCaxEDj5c5EQCWJh5EJO+6fdnF7oqFrfGk2kx
-54kY8wBfYEr2psXLTuidKLmxu1gZLymRcH7oDHggFahii0HqXGUSrcTzsuqLI83/
-ulQ0VmJhkY9zooTgh+NhUvKKVGNy7O2rNQLzPXFyeun9bOeKhKiCnUIt0kxtFJPg
-l6u8X46qg4uKqVbDbv2oUV5jTfVDlGwJVAWvC8JPC8N1P0BRmGGqA3NGxpmMRBa6
-fQIDAQAB
------END PUBLIC KEY-----"}},"a4304752b0a81316df3d0d1c331e882fe284f1239fe394f31211a19da02e16bd":{"keytype":"rsa","keyval":{"public":"-----BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeX9pEiyvBLIl46oLfUJ
-KphECc0sojOmVEtp9rAP/aChHdYHl3usyOexNyQNX7vucmk9rnK/aOFJwo5Mtf5r
-Yl4sIMK5jqI2mvjGjuminjBDGoLCRiK3mFxAGyr4t0AtxtpW8AR4tvgUfl3DS+aB
-XRYBhsx6zndQsPfrggakyv9xeA4uORDQ2ivrq+4BkDCXo65ZA61qFSsfPaShfij0
-klGPLVbyTMc+offlfiiL6ogd6MI49wNb+IDslAPfwrPZ4M3SLWVMmb6+JclFzwp0
-p+CURLWXCptDC9muFSMxZTwaBWBiresHEN36zBoU27ziZCNHpaIgGhjRaJVjzjBo
-MQIDAQAB
------END PUBLIC KEY-----"}},"dbfa99f76c6a89191a6747a5e6ed63da202ce77a1f32ae85e152f325ca9a4117":{"keytype":"rsa","keyval":{"public":"-----BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr0weyzfZ42HVeafaN3WN
-Tz9PNsy/p2AqgPWYLD/lZRO0VwTRfQ/IM30NQ2DdK1Nu/uEkKTFs+Opx1sL+ezCJ
-M2BtqxZKzWlpdGR5Fu2VhXC+pd4FzSBPD3H70Ln85fsww2dnJOVZyxL++vgRKj/I
-QM26ind9pkDhdowSj9bu45Sn8M1BJ7WWoxj4JMficgeSQ4DhrP6Xx326hLLOp0uf
-LxJbNNCeBqlmpZR+wi5MO21L+1JLEhFxCpmrhii4IILi6zooi5Je8RLW544IkzQE
-5sCX/q9PdnEXc7yOKksja9J6tHcUR6cLWdbGAH4MpUGaT91eDKMh9nNNtwoDpDNV
-qwIDAQAB
------END PUBLIC KEY-----"}},"ed3c845525d34937bf0584989a76fa300c0a6072de714b11b8dca535e10b9088":{"keytype":"rsa","keyval":{"public":"-----BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAndqFFxVnq7FjihMB7sBj
-fMMIS2112HB0PauY7wDQ8gTnfbWkCOOQ2kvh0f8Ph41rQ1iZiPaZq+eQ+yqhPCsP
-JKSeq9H8oOCon4JI5afSTUTkC0NmA1SN3cMMJvUgNr+uBWOc+IHr90o6xBTuzplm
-nzzjGCGNaOMLt7P3yuF8q9UXb1DBOBvqYutGB5UB+9Ma0K4c5lMnUy0IVb6j1tEC
-FKSi4RTepA5UAOV5LE2T6Gs89kRjhTxvVsKAAj92z3VGX5pJR9zm6ZrAbjSen9Lf
-vFWgd2Hz1Qy4d9Jm0iSaJb5VG06/O4JMT1FXfIv2OP5NlzKoyDxp5ZEVLHWNksHH
-awIDAQAB
------END PUBLIC KEY-----"}}},"roles":{"root":{"keyids":["ed3c845525d34937bf0584989a76fa300c0a6072de714b11b8dca535e10b9088"],"threshold":1},"snapshot":{"keyids":["dbfa99f76c6a89191a6747a5e6ed63da202ce77a1f32ae85e152f325ca9a4117"],"threshold":1},"targets":{"keyids":["0bde74244f238cd6d4e3839d35a5b248d6cde5759b760ebdbee45a386109a41a"],"threshold":1},"timestamp":{"keyids":["a4304752b0a81316df3d0d1c331e882fe284f1239fe394f31211a19da02e16bd"],"threshold":1}},"version":1}}
\ No newline at end of file
diff --git a/tests/cjson/root.json b/tests/cjson/root.json
deleted file mode 100644
index 4aee181..0000000
--- a/tests/cjson/root.json
+++ /dev/null
@@ -1,67 +0,0 @@
-{
-  "signatures": [
-    {
-      "keyid": "ed3c845525d34937bf0584989a76fa300c0a6072de714b11b8dca535e10b9088",
-      "method": "rsassa-pss-sha256",
-      "sig": "49bdc0586c83afad062c608a70a5cfd6dd32bf47eb7830960322723615f723fbf43c7d80dab455b08114624d89de740b2547bece8fda01a8acaecf651fcbe98f291971de695fb2f00889bd1ec076e9d431c4c004791dc5e223f023301eca865c0ede005952dfa4fc7b1a591f8875445872d6162039d5e59418998e0c99a15ad28689b82b72099926354ca253cffafe7a3f7ececb9ecddda35cecb05ea9ca184c7ea942ea8a1a49b7445803dd3a14d74697d220f59cef5d56bc9b640d8aca2328f0d6ea4aa25ba79164ecdf31904a176b6100188970d37860c2612cf4571613fdbaa29080be50cae2966dd46a677acaf1dd500d7a86d025877aab0fdaa72f1856"
-    }
-  ],
-  "signed": {
-    "_type": "Root",
-    "consistent_snapshot": false,
-    "expires": "2038-01-19T03:14:06Z",
-    "keys": {
-      "0bde74244f238cd6d4e3839d35a5b248d6cde5759b760ebdbee45a386109a41a": {
-        "keytype": "rsa",
-        "keyval": {
-          "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8QLzN27B3+DKhWR8nJZO\nScZ6XS2mubhqcr3giT+WJejjVH4zIlaeC5tosaY96VKI5vRd4aFgQwq2XEx+YTJM\ndAaUGOUSvPYa+iv+O0ilPeYyXazoCaxEDj5c5EQCWJh5EJO+6fdnF7oqFrfGk2kx\n54kY8wBfYEr2psXLTuidKLmxu1gZLymRcH7oDHggFahii0HqXGUSrcTzsuqLI83/\nulQ0VmJhkY9zooTgh+NhUvKKVGNy7O2rNQLzPXFyeun9bOeKhKiCnUIt0kxtFJPg\nl6u8X46qg4uKqVbDbv2oUV5jTfVDlGwJVAWvC8JPC8N1P0BRmGGqA3NGxpmMRBa6\nfQIDAQAB\n-----END PUBLIC KEY-----"
-        }
-      },
-      "a4304752b0a81316df3d0d1c331e882fe284f1239fe394f31211a19da02e16bd": {
-        "keytype": "rsa",
-        "keyval": {
-          "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeX9pEiyvBLIl46oLfUJ\nKphECc0sojOmVEtp9rAP/aChHdYHl3usyOexNyQNX7vucmk9rnK/aOFJwo5Mtf5r\nYl4sIMK5jqI2mvjGjuminjBDGoLCRiK3mFxAGyr4t0AtxtpW8AR4tvgUfl3DS+aB\nXRYBhsx6zndQsPfrggakyv9xeA4uORDQ2ivrq+4BkDCXo65ZA61qFSsfPaShfij0\nklGPLVbyTMc+offlfiiL6ogd6MI49wNb+IDslAPfwrPZ4M3SLWVMmb6+JclFzwp0\np+CURLWXCptDC9muFSMxZTwaBWBiresHEN36zBoU27ziZCNHpaIgGhjRaJVjzjBo\nMQIDAQAB\n-----END PUBLIC KEY-----"
-        }
-      },
-      "dbfa99f76c6a89191a6747a5e6ed63da202ce77a1f32ae85e152f325ca9a4117": {
-        "keytype": "rsa",
-        "keyval": {
-          "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr0weyzfZ42HVeafaN3WN\nTz9PNsy/p2AqgPWYLD/lZRO0VwTRfQ/IM30NQ2DdK1Nu/uEkKTFs+Opx1sL+ezCJ\nM2BtqxZKzWlpdGR5Fu2VhXC+pd4FzSBPD3H70Ln85fsww2dnJOVZyxL++vgRKj/I\nQM26ind9pkDhdowSj9bu45Sn8M1BJ7WWoxj4JMficgeSQ4DhrP6Xx326hLLOp0uf\nLxJbNNCeBqlmpZR+wi5MO21L+1JLEhFxCpmrhii4IILi6zooi5Je8RLW544IkzQE\n5sCX/q9PdnEXc7yOKksja9J6tHcUR6cLWdbGAH4MpUGaT91eDKMh9nNNtwoDpDNV\nqwIDAQAB\n-----END PUBLIC KEY-----"
-        }
-      },
-      "ed3c845525d34937bf0584989a76fa300c0a6072de714b11b8dca535e10b9088": {
-        "keytype": "rsa",
-        "keyval": {
-          "public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAndqFFxVnq7FjihMB7sBj\nfMMIS2112HB0PauY7wDQ8gTnfbWkCOOQ2kvh0f8Ph41rQ1iZiPaZq+eQ+yqhPCsP\nJKSeq9H8oOCon4JI5afSTUTkC0NmA1SN3cMMJvUgNr+uBWOc+IHr90o6xBTuzplm\nnzzjGCGNaOMLt7P3yuF8q9UXb1DBOBvqYutGB5UB+9Ma0K4c5lMnUy0IVb6j1tEC\nFKSi4RTepA5UAOV5LE2T6Gs89kRjhTxvVsKAAj92z3VGX5pJR9zm6ZrAbjSen9Lf\nvFWgd2Hz1Qy4d9Jm0iSaJb5VG06/O4JMT1FXfIv2OP5NlzKoyDxp5ZEVLHWNksHH\nawIDAQAB\n-----END PUBLIC KEY-----"
-        }
-      }
-    },
-    "roles": {
-      "root": {
-        "keyids": [
-          "ed3c845525d34937bf0584989a76fa300c0a6072de714b11b8dca535e10b9088"
-        ],
-        "threshold": 1
-      },
-      "snapshot": {
-        "keyids": [
-          "dbfa99f76c6a89191a6747a5e6ed63da202ce77a1f32ae85e152f325ca9a4117"
-        ],
-        "threshold": 1
-      },
-      "targets": {
-        "keyids": [
-          "0bde74244f238cd6d4e3839d35a5b248d6cde5759b760ebdbee45a386109a41a"
-        ],
-        "threshold": 1
-      },
-      "timestamp": {
-        "keyids": [
-          "a4304752b0a81316df3d0d1c331e882fe284f1239fe394f31211a19da02e16bd"
-        ],
-        "threshold": 1
-      }
-    },
-    "version": 1
-  }
-}